shiro authentication

Authentication , that is, who can prove that he is himself in the application. Generally, some identification information such as their identity ID is provided to indicate that he is himself, such as ID card, user name/password to prove.

In shiro, the user needs to provide principals (identity) and credentials (proof) to shiro, so that the application can verify the user's identity:

principals : Identity, that is, the identity attribute of the principal, which can be anything, such as username, email, etc., it is unique. A principal can have multiple principals, but there is only one Primary principals, usually username/password/mobile phone number.

credentials : Proofs/credentials, i.e. security values ​​known only to the subject, such as passwords/digital certificates, etc.

The most common combination of principals and credentials is username/password.

 

For example, AuthenticationToken only provides two methods to obtain identity and credentials respectively. The implementation of AuthenticationToken is generally UsernamePasswordToken, but it can be customized, such as JWT token.

public interface AuthenticationToken extends Serializable {

    Object getPrincipal();
    Object getCredentials();

}

 

For the authentication process, we can also look at it from both external and internal perspectives

First, the external implementation process

1. First prepare some user identities/credentials (shiro.ini)

Java code  
  1. [users]  
  2. zhang=123  
  3. wang=123  

The ini configuration file is used here, and two subjects are specified through [users]: zhang/123, wang/123.

  

2. Test case

@Test  
 public  void testHelloworld() {  
     // 1. Get the SecurityManager factory, where the Ini configuration file is used to initialize the SecurityManager  
    Factory<org.apache.shiro.mgt.SecurityManager> factory =  
            new IniSecurityManagerFactory( " classpath:shiro.ini " );  
     // 2. Get the SecurityManager instance and bind it to SecurityUtils   
    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();  
    SecurityUtils.setSecurityManager(securityManager);  
    // 3. Get Subject and create username/password authentication Token (ie user identity/credential)   
    Subject subject = SecurityUtils.getSubject();  
    UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");  
  
    try {  
         // 4. Login, that is, authentication   
        subject.login(token);  
    } catch (AuthenticationException e) {  
         // 5. Authentication failed   
    }  
  
    Assert.assertEquals( true , subject.isAuthenticated()); // Assert that the user is logged   in
  
    // 6. Exit   
    subject.logout();  
}  

2.1. First create a SecurityManager factory through new IniSecurityManagerFactory and specifying an ini configuration file;

2.2. Then get SecurityManager and bind it to SecurityUtils, this is a global setting, you can set it once;

2.3. Obtain the Subject through SecurityUtils, which will be automatically bound to the current thread; if the web environment needs to be unbound at the end of the request; then obtain the authentication Token, such as username/password;

2.4. Call the subject.login method to log in, which will be automatically delegated to the SecurityManager.login method to log in;

2.5. If authentication fails, please catch AuthenticationException or its subclasses, such as: DisabledAccountException (disabled account), LockedAccountException (locked account), UnknownAccountException (wrong account), ExcessiveAttemptsException (too many login failures), IncorrectCredentialsException ( Incorrect credentials), ExpiredCredentialsException (expired credentials), etc., please check the inheritance relationship for details; for the display of error messages on the page, it is better to use "username/password error" instead of "username error"/"password error" , to prevent some malicious users from illegally scanning the account database;

2.6. Finally, you can call subject.logout to exit, which will automatically delegate to the SecurityManager.logout method to exit.

 

3. Realm implementation

The org.apache.shiro.realm.Realm interface is as follows: 

String getName(); // Return a unique Realm name   
boolean supports(AuthenticationToken token); // Determine whether this Realm supports this Token   
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)  
 throws AuthenticationException;   // Acquire authentication information according to Token

Custom Realm implementation:

public class MyRealm1 implements Realm {  
    @Override  
    public String getName() {  
        return "myrealm1";  
    }  
    @Override  
    public boolean supports(AuthenticationToken token) {  
        //仅支持UsernamePasswordToken类型的Token  
        return token instanceof UsernamePasswordToken;   
    }  
    @Override  
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {  
        String username = (String)token.getPrincipal();   // Get the username   
        String password = new String(( char [])token.getCredentials()); // Get the password   
        if (! " zhang " .equals(username) ) {  
             throw  new UnknownAccountException(); // if the username is wrong   
        }  
         if (! " 123 " .equals(password)) {  
             throw  new IncorrectCredentialsException(); // if the password is wrong   
        }  
         //If authentication is successful, return an AuthenticationInfo implementation;   
        return  new SimpleAuthenticationInfo(username, password, getName());  
    }  
}   

 

Second, from the perspective of internal implementation principles

The process is as follows:

1. First, call Subject.login(token) to log in, which will be automatically delegated to Security Manager, which must be set through SecurityUtils.setSecurityManager() before calling;

2. SecurityManager is responsible for the real authentication logic; it will delegate to Authenticator for authentication;

3. Authenticator is the real authenticator, the core authentication entry point in Shiro API, here you can customize and insert your own implementation;

4. Authenticator may delegate to the corresponding AuthenticationStrategy for multi-Realm authentication. By default, ModularRealmAuthenticator will call AuthenticationStrategy for multi-Realm authentication;

5. The Authenticator will pass the corresponding token into Realm, and obtain authentication information from Realm. If it does not return/throw an exception, it means that the authentication fails. Multiple Realms can be configured here, which will be accessed according to the corresponding order and strategy.

 

Excerpted from: Chapter 2 Authentication - "Learn Shiro With Me"

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325084075&siteId=291194637