Shiro practical tutorial (full)

Table of contents

1. Authority management

1.1 What is rights management

1.2 What is identity authentication

1.3 What is authorization

2. What is shiro

3. Shiro's core architecture

3.1 Subject

3.2 SecurityManager

3.3 Authenticator

3.4 Authorizer

3.5 Realm

3.6 SessionManager

3.7 SessionDAO

3.8 CacheManager

3.9 Cryptography

4. Authentication in shiro

4.1 Authentication

4.2 Key objects of authentication in shiro

4.3 Certification process

4.4 Development of certification

4.5 Custom Realm

4.6 Using MD5 and Salt

5. Authorization in shiro

5.1 Authorization

5.2 Key objects

5.3 Authorization process

5.4 Authorization method

5.5 Permission Strings

5.6 Implementation method of authorized programming in shiro

5.7 Development Authorization

6. Integrate SpringBoot project actual combat

6.0 Integration Ideas

6.1 Create a springboot project

6.2 Introducing shiro dependencies

6.3 Configure shiro environment

6.4 Common filters

6.5 Authentication implementation

6.6 Withdrawal from certification

6.7 Implementation of MD5 and Salt authentication

This is the end of today's sharing

Creation is not easy, likes, comments and mutual relations


 

1. Authority management

1.1 What is rights management

Basically, any system that involves user participation must perform authority management. Authority management belongs to the category of system security. To achieve authority management, users can access and only access authorized resources 对用户访问系统的控制according to security rules or security policies .

Rights management includes users 身份认证and 授权two parts, referred to as 认证授权. For resources that require access control, users must first go through identity authentication, and only after passing the authentication can the user have access to the resource.

1.2 What is identity authentication

身份认证, is the process of judging whether a user is a legitimate user. The most commonly used simple identity authentication method is that the system checks the user name and password entered by the user to see if it is consistent with the user name and password stored in the system to determine whether the user's identity is correct. For systems such as fingerprints , fingerprints are required; for card swiping systems such as hardware keys, card swiping is required.

1.3 What is authorization

授权,即访问控制, to control who can access which resources. After authentication, the subject needs to be assigned permissions to access system resources, and some resources cannot be accessed without permissions


2. What is shiro

Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

Shiro is a powerful and easy-to-use Java security framework that performs authentication, authorization, encryption, and session management. Using Shiro's easy-to-understand API, you can quickly and easily secure any application—from the smallest mobile app to the largest web and enterprise application.

Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架。


3. Shiro's core architecture

 

3.1 Subject

Subject即主体, the external application interacts with the subject, the subject records the current operating user, and understands the concept of the user as the subject of the current operation, which may be a user requesting through a browser or a running program. Subject is an interface in Shiro, which defines many methods related to authentication and authorization. The external program performs authentication and authorization through the subject, and the subject performs authentication and authorization through the SecurityManager security manager.

3.2 SecurityManager

SecurityManager即安全管理器, for security management of all subjects, it is the core of shiro, responsible for security management of all subjects. The authentication and authorization of the subject can be completed through the SecurityManager. In essence, the SecurityManager is authenticated through the Authenticator, authorized through the Authorizer, and session management through the SessionManager.

SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口。

3.3 Authenticator

Authenticator即认证器, to authenticate the user identity, Authenticator is an interface, shiro provides ModularRealmAuthenticator implementation class, ModularRealmAuthenticator can basically meet most of the needs, you can also customize the authenticator.

3.4 Authorizer

Authorizer即授权器, the user passes the authentication through the authenticator. When accessing the function, it needs to use the authorizer to determine whether the user has the operation authority of this function.

3.5 Realm

Realm即领域, which is equivalent to the datasource data source. SecurityManager needs to obtain user permission data through Realm for security authentication. For example, if user identity data is in the database, Realm needs to obtain user identity information from the database.

  • Note: Do not understand realm as just fetching data from the data source, there are related codes for authentication and authorization verification in realm.

3.6 SessionManager

sessionManager即会话管理, the shiro framework defines a set of session management, which does not depend on the session of the web container, so shiro can be used in non-web applications, and can also centralize the session management of distributed applications. This feature enables it to achieve single sign-on .

3.7 SessionDAO

SessionDAO即会话dao, is a set of interfaces for session operations. For example, if you want to store the session in the database, you can store the session in the database through jdbc.

3.8 CacheManager

CacheManager即缓存管理, store user permission data in the cache, which can improve performance.

3.9 Cryptography

Cryptography即密码管理, shiro provides a set of encryption/decryption components for easy development. For example, it provides common functions such as hashing and encryption/decryption.


4. Authentication in shiro

4.1 Authentication

Identity authentication is the process of judging whether a user is a legitimate user. The most commonly used simple identity authentication method is that the system checks the user name and password entered by the user to see if it is consistent with the user name and password stored in the system to determine whether the user's identity is correct.

4.2 Key objects of authentication in shiro

  • Subject: subject

The user who accesses the system, the subject can be a user, a program, etc., and the person who performs authentication is called the subject;

  • Principal: identity information

It is the identification of the subject (subject) for identity authentication. The identification must have 唯一性, such as user name, mobile phone number, email address, etc. A subject can have multiple identities, but must have a primary identity (Primary Principal).

  • credential: credential information

It is security information that only the subject knows, such as passwords, certificates, etc.

4.3 Certification process

 

4.4 Development of certification

1. Create a project and introduce dependencies

 

2. Import the shiro configuration file and add the following configuration

 

 

3. Develop authentication code

/**
 * @author: mosin
 * @version: v1.0
 */
public class ShiroTest {

    public static void main(String[] args) {
        //创建默认的安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //创建安全管理器需要的realm对象
        IniRealm iniRealm = new IniRealm("classpath:realm.ini");
        //安全管理器设置realm对象
        defaultSecurityManager.setRealm(iniRealm);
        //将安全管理器注入安全工具类   用于获取认证的主体
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取认证的主体
        Subject subject = SecurityUtils.getSubject();
        //创建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosin", "1234");

        try {
            //认证 通过没有任何的异常
            subject.login(usernamePasswordToken);
            //验证是否通过
            boolean authenticated = subject.isAuthenticated();
            System.out.println("认证通过:"+authenticated);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!");
        }

    }

}

 

  • DisabledAccountException (account is disabled)

  • LockedAccountException (account is locked)

  • ExcessiveAttemptsException (Excessive login failures)

  • ExpiredCredentialsException (credentials expired), etc.


4.5 Custom Realm

The program above uses IniRealm that comes with Shiro. IniRealm reads user information from the ini configuration file. In most cases, it needs to read user information from the system database, so you need to customize the realm.

1. Realm provided by Shiro

2. According to the authentication source code authentication, SimpleAccountRealm is used

 

SimpleAccountRealm的部分源码中有两个方法一个是 认证 一个是 授权,

public class SimpleAccountRealm extends AuthorizingRealm {
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        SimpleAccount account = getUser(upToken.getUsername());

        if (account != null) {

            if (account.isLocked()) {
                throw new LockedAccountException("Account [" + account + "] is locked.");
            }
            if (account.isCredentialsExpired()) {
                String msg = "The credentials for account [" + account + "] are expired";
                throw new ExpiredCredentialsException(msg);
            }

        }

        return account;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = getUsername(principals);
        USERS_LOCK.readLock().lock();
        try {
            return this.users.get(username);
        } finally {
            USERS_LOCK.readLock().unlock();
        }
    }
}

 

3. Custom realm

/**
 * 自定义realm
 */
public class CustomerRealm extends AuthorizingRealm {
    //认证方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    //授权方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String) token.getPrincipal();
        if("mosin".equals(principal)){
            return new SimpleAuthenticationInfo(principal,"123",this.getName());
        }
        return null;
    }
}

4. Use custom Realm authentication

public class TestAuthenticatorCustomerRealm {
    public static void main(String[] args) {
        //创建securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //IniRealm realm = new IniRealm("classpath:realm.ini");
        //设置为自定义realm获取认证数据
        defaultSecurityManager.setRealm(new CustomerRealm());
        //将安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("mosin", "1234");
        try {
            subject.login(token);//用户登录
            System.out.println("登录成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!!!");
        }

    }
}

4.6 Using MD5 and Salt

The practical application is to store the salt and the hashed value in the database, and the automatic realm takes out the salt and the encrypted value from the database, and Shiro completes the password verification.

1. Customize the realm of md5+salt

/**
 * 自定义md5+salt realm
 */
public class CustomerMD5Realm extends AuthorizingRealm {

    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String principal = (String) token.getPrincipal();
        //根据用户名查询数据库
        if("mosin".equals(principal)){
            // 参数1:用户名  参数2:密码 参数3:盐 参数4:自定义realm的名字
            System.out.println(this.getName());
            return new SimpleAuthenticationInfo(principal, "800d63a19662b2ba95bc2ffa01ab4804", ByteSource.Util.bytes("mosin"),this.getName());
        }
        return null;
    }
}

2. Use md5 + salt authentication

public class CustomerMD5RealmTest {

    public static void main(String[] args) {

        //创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //创建自定义MD5Realm对象
        CustomerMD5Realm customerMD5Realm = new CustomerMD5Realm();
        //创建密码认证匹配器对象
        HashedCredentialsMatcher md5 = new HashedCredentialsMatcher("MD5");
        //设置散列的次数
        md5.setHashIterations(1024);
        //设置密码认证匹配器对象
        customerMD5Realm.setCredentialsMatcher(md5);
        //设置安全管理器的 认证安全数据源
        defaultSecurityManager.setRealm(customerMD5Realm);
        //设置安全工具类的安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取认证的主体
        Subject subject = SecurityUtils.getSubject();
        //创建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosi", "12345");

        //登录认证
        try {
            subject.login(usernamePasswordToken);
            System.out.println("认证通过:"+subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!!!");
        }

    }
}

5. Authorization in shiro

5.1 Authorization

Authorization, or access control, controls who can access which resources. After identity authentication, the subject needs to be assigned permissions to access system resources, and some resources cannot be accessed without permissions.

5.2 Key objects

Authorization can be simply understood as who performs How operations on what (which):

Who,即主体(Subject), the principal needs to access resources in the system.

What,即资源(Resource), such as system menus, pages, buttons, class methods, system product information, etc. The resource includes 资源类型and 资源实例, for example 商品信息为资源类型, the commodity whose type is t01 is 资源实例, and the commodity information whose serial number is 001 also belongs to the resource instance.

How,权限/许可(Permission), which stipulates the subject's permission to operate resources. It is meaningless to leave the resource without permission, such as user query permission, user add permission, call permission of a certain class method, modification permission of the user numbered 001, etc. Through the permission, it can be known which resources the subject has What operating permissions are there.

5.3 Authorization process

5.4 Authorization method

  • Role-Based Access Control

    • RBAC role-based access control (Role-Based Access Control) is a role-centric access control

       

       

  • Resource-Based Access Control

    • RBAC resource-based access control (Resource-Based Access Control) is resource-centric access control

 

5.5 Permission Strings

The rules of the permission string are: resource identifier: operation: resource instance identifier , which means which operation is performed on which instance of which resource, ":" is the separator of resource/operation/instance, permission string can also use * wildcard.

example:

  • User creation permission: user:create, or user:create:*

  • The user can modify the permission of instance 001: user:update:001

  • All permissions for user instance 001: user:*:001

5.6 Implementation method of authorized programming in shiro

  • programmatic

 

Annotation

 

Tabbed

 

 

5.7 Development Authorization

1. Realm realization

public class CustomerRealm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String primaryPrincipal = (String) principals.getPrimaryPrincipal();
        System.out.println("primaryPrincipal = " + primaryPrincipal);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRole("admin");

        simpleAuthorizationInfo.addStringPermission("user:update:*");
        simpleAuthorizationInfo.addStringPermission("product:*:*");


        return simpleAuthorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String) token.getPrincipal();
        if("xiaochen".equals(principal)){
            String salt = "Q4F%";
            return new SimpleAuthenticationInfo(principal,password, 
                                                ByteSource.Util.bytes(salt),this.getName());
        }
        return null;
    }

}

 

 

2. Authorization

public class CustomerMD5RealmTest {

    public static void main(String[] args) {

        //创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //创建自定义MD5Realm对象
        CustomerMD5Realm customerMD5Realm = new CustomerMD5Realm();
        //创建密码认证匹配器对象
        HashedCredentialsMatcher md5 = new HashedCredentialsMatcher("md5");
        //设置加密的次数
        md5.setHashIterations(1024);
        //设置密码认证匹配器对象
        customerMD5Realm.setCredentialsMatcher(md5);
        //设置安全管理器的 认证安全数据源
        defaultSecurityManager.setRealm(customerMD5Realm);
        //设置安全工具类的安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);

        //获取认证的主体
        Subject subject = SecurityUtils.getSubject();
        //创建令牌
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("mosin", "12345");

        //登录认证
        try {
            subject.login(usernamePasswordToken);
            System.out.println("认证通过:"+subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!!!");
        }

        //基于角色的控制
        //单角色控制
        System.out.println("========hasRole==========");
        boolean admin = subject.hasRole("admin");
        System.out.println("hash admin role:"+admin);

        //多角色控制
        System.out.println("========hasAllRoles==========");
        List<String> roles = Arrays.asList("admin", "user");
        boolean booleans = subject.hasAllRoles(roles);
        System.out.println("booleans = " + booleans);

        // 基于任意角色的控制
        System.out.println("========hasRoles==========");
        boolean[] booleans1 = subject.hasRoles(roles);
        for (boolean b : booleans1) {
            System.out.println("b = " + b);
        }

        //基于权限字符串的权限控制
        System.out.println("========isPermitted==========");
        boolean permitted = subject.isPermitted("user:update:*");
        System.out.println("permitted = " + permitted);

        //分别具有哪些权限
        boolean[] permitted1 = subject.isPermitted("user:update:*", "product:update:*");
        for (boolean b : permitted1) {
            System.out.println("b = " + b);
        }
        //同时具有哪些权限
        boolean permittedAll = subject.isPermittedAll("user:update:*", "product:update:*");
        System.out.println("permittedAll = " + permittedAll);

    }
}

6. Integrate SpringBoot project actual combat

6.0 Integration Ideas

6.1 Create a springboot project

6.2 Introducing shiro dependencies

6.3 Configure shiro environment

0. Create a configuration class

 

1. Configure shiroFilterFactoryBean

 

2. Configure WebSecurityManager

 

Create a custom realm

 

 

4. Configure a custom realm

 

5. Write the main page index.jsp

 

6. Start the project and visit index.jsp

 

By default, after the shiro environment is configured, there is no permission control for any resource in the project in the default environment, and all resources in the project can now be accessed through the path

7. Add permission control

Modify ShiroFilterFactoryBean configuration

 

8. Restart project access view

 

6.4 Common filters

  • Note: shiro provides multiple default filters, we can use these filters to configure and control the permissions of the specified url:

configuration abbreviation corresponding filter Function
anon AnonymousFilter The specified url can be accessed anonymously
authc FormAuthenticationFilter The specified url requires form form login. By default , parameters such as username, password, and so on will be obtained from the request and try to log in. If the login fails, it will jump to the path configured by loginUrl. rememberMeWe can also use this filter as the default login logic, but generally we write the login logic in the controller by ourselves. If we write it ourselves, the information returned by the error can be customized.
authcBasic BasicHttpAuthenticationFilter The specified url requires basic login
logout LogoutFilter Logout filter, configure the specified url to realize the logout function, very convenient
noSessionCreation NoSessionCreationFilter Disable session creation
perms PermissionsAuthorizationFilter Specified permissions are required to access
port PortFilter Need to specify the port to access
rest HttpMethodPermissionFilter Converting the http request method into a corresponding verb to construct a permission string does not make much sense. If you are interested, read the source code comments yourself.
roles RolesAuthorizationFilter A role is required to access
ssl SslFilter Requires https request to access
user UserFilter Requires a logged in or "remember me" user to access

6.5 Authentication implementation

1. Develop the authentication interface in login.jsp

 

2. Develop controllers

@Controller
@RequestMapping("user")
public class UserController {
  /**
    * 用来处理身份认证
    * @param username
    * @param password
    * @return
    */
  @RequestMapping("login")
  public String login(String username,String password){
    //获取主体对象
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.login(new UsernamePasswordToken(username,password));
      return  "redirect:/index.jsp";
    } catch (UnknownAccountException e) {
      e.printStackTrace();
      System.out.println("用户名错误!");
    }catch (IncorrectCredentialsException e){
      e.printStackTrace();
      System.out.println("密码错误!");
    }
    return "redirect:/login.jsp";
  }
}

 

  • Use subject.login for authentication during authentication

3. Return static data in the development realm (not connected to the database)

4. Start the project with static data defined in realm for authentication

 

 

6.6 Withdrawal from certification

1. Development page exit connection

 

2. Develop controllers

 

3. Modify the exit connection access exit path

 

4. After exiting, access to restricted resources immediately returns to the authentication interface

 

6.7 Implementation of MD5 and Salt authentication

1. Development database registration

0. Develop registration interface

1. Create a data table structure

 

 

2. The project introduces dependencies

 

3. Configure the application.properties configuration file

 

4. Create entity

 

5. Create a DAO interface

 

6. Develop mapper configuration files

 

7. Develop service interface

 

8. Create a salt tool class

 

9. Develop service implementation classes

 

10. Develop Controller

 

11. Start the project to register

 

2. Develop database authentication

0. Develop DAOs

 

1. Develop mapper configuration files

 

2. Develop Service interface

 

3. Develop Service implementation class

 

4. Develop a tool class for obtaining bean objects in the factory

 

5. Modify the custom realm

 

6. Modify realm in ShiroConfig to use credential matcher and hash

 

This is the end of today's sharing

Creation is not easy, likes, comments and mutual relations

 

 

 

 

 

Guess you like

Origin blog.csdn.net/swy2560666141/article/details/130365895