Introduction and Application of Shiro - --------------------------- Security Framework

Keywords: Java Shiro Database Apache Session

Introduction to Shiro

Shiro is an open source project under Apache. It is a relatively simple and easy-to-use security framework. It provides authentication, authorization, encryption, session management and other functions.

Shiro's Three Core Components

Subject: Understandable as the current user principal, all Subjects are bound to a Security Manager. Interacting with Subject is essentially interacting with Security Manager.

Security Manager: Shiro's core, which manages all Subject s, is mainly used to coordinate various security components within Shiro and can be regarded as Shiro's steward.

Realm: It can be understood as a bridge between Shiro and database. Whether Shiro authenticates or authorizes, data comparison is needed, and it is a bridge between Shiro and database to get data. Component change is written by developers, which usually defines a class to inherit AuthorizingRealm class, and then rewrite the method inside.

Common uses of Shiro

Generally speaking, we use Shiro for authentication, authorization and session management.

Authentication - --- Authentication of users at login time, how to verify is written by developers, and corresponding logic will be written in Realm's authentication method.

[Authorization] - - - Authorize the authenticated user with privileges and roles, which will trigger validation when some methods need access privileges and roles. Only with the corresponding privileges and roles can access, which methods need access privileges or roles are also defined by developers.

Simple Use of Shiro

Adding dependencies


<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.2.2</version>
</dependency>

If used EhCache When caching, you need to add its dependencies
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>>1.4.0</version>
</dependency>

Custom Realm

public class MyRealm extends AuthorizingRealm
{
   
    //Note that the custom Realm inherits the AuthorizingRealm class and overrides its authentication, authorization methods

    /**
     * To grant authorization
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
    {
        String userId = ShiroUtils.getUserId();    //This is the id of the user who obtained the authentication, and can enter the modified method to prove that the user has passed the authentication.
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        // Role Joining AuthorizationInfo Authentication Object
        info.setRoles(The parameters are based on the user id The set of roles found in the database, Set Assembled);
        // Access to AuthorizationInfo Authentication Objects
        info.setStringPermissions(The parameters are based on the user id The set of privileges found in the database, Set Assembled);
        return info;
    }

    /**
     * Login Authentication
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
    {
        //This object is an object encapsulating a more password of user account. It is the account password recorded there, not the account password checked out from the database.
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;  
        String userId = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null)
        {
            password = new String(upToken.getPassword());
        }

        Nurse user;
       
        user = Query the database according to the user's account number;   //This step is to look up users in the database based on the account number. 
        
        if(user==null){
            throw new UnknownAccountException("ERROR Incorrect username or password!");  //throw
        {
        //Note that these parameters, the first two of which are data retrieved from the database, are not data retrieved from the parameter token.
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }
}

Configure Shiro

@Configuration
public class ShiroConfig {


    /**
     * Custom Realm
     */
    @Bean
    public MyRealm myRealm()
    {
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }

    /**
     * Safety Manager
     */
    @Bean
    public SecurityManager securityManager(MyRealm myRealm)
    {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // Set realm.
        securityManager.setRealm(userRealm);
        return securityManager;
    }


    private LogoutFilter logoutFilter() { // Use in ShiroFilterFactoryBean
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setRedirectUrl("/login"); // Home page path, page returned after logout
        return logoutFilter;
    }
    
    /**
     * Open Shiro Annotation Notifier. Note this configuration. If it is not configured, the annotation will be invalid.
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * Shiro Filter configuration
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro's core security interface, this property is required
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // If authentication fails, jump to the configuration of the login page
        shiroFilterFactoryBean.setLoginUrl(Route);
        // Fail to authenticate permission, then jump to the specified page
        shiroFilterFactoryBean.setUnauthorizedUrl(Route);
        // Shiro Connection Constraint Configuration, the Definition of Filter Chain
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // Setting up anonymous access to static resources
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/ruoyi.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/image/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/plugins/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
  
        // Access that does not need to be intercepted
        filterChainDefinitionMap.put("/login", "anon");
        Map<String, Filter> filters = new LinkedHashMap<>();
        // If logout is successful, jump to the specified page
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);
        // All requests require authentication
        filterChainDefinitionMap.put("/**", "user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
}

Using Authentication Function

/**
     * User login
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(User user) {
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getName(), user.getPassword());
        Subject subject = SecurityUtils.getSubject();  //Getting shiro's entity object
        try {
            // Login operation
            subject.login(usernamePasswordToken);      //Call the authentication method in shiro to verify the account password. This line is the key. Calling it triggers the authentication method.
            User user = (UserInfo) subject.getPrincipal();     //Getting the Authenticated Subject Object in shiro
            return "index";
        } catch (Exception e) {
            return "login";
        }
    }

Using Authorization Function

    /*
        It's important to note that only using shiro's annotations can authorization be used, and authorization role validation can be said.
        
        Several commonly used annotations:
        @RequiresPermissions("Privileges - ----- This is a permission annotation, which can only be accessed when the user has the permission.
        @RequiresRoles("Roles - --------------- This is a role annotation, which can only be accessed when the user has the role.
        @RequiresAuthentication()----------Indicates that the current Subject has been authenticated by login and reported an exception without authentication
        
        < shiro Annotations can be used together in >
    */
    
--------Use examples:    
    
    /**
     * delete user
     */
    @RequiresPermissions("userInfo:del")                //Only shiro's annotations trigger authorization validation, which is one of the annotations
    @RequestMapping(value = "/del", method = RequestMethod.GET)
    public String del() {
        return "Delete user name bobo Success";
    }

The above Shiro is just simple to use, without adding Ehcache cache and encryption, without using remember me, and without using Session management.

    Thank you for reading. If there are any mistakes, please point them out.

The shiro series of bloggers with this link is very detailed, click on the past

Posted by printf on Sun, 01 Sep 2019 20:27:25 -0700