Apache Shiro User Manual (2) Shiro certification, apacheshiro
Authentication is the process of verifying user identity. During authentication, You need to submit the entity information (Principals) and Credentials to check whether the user is legal. The most common "entity/credential" combination is "User Name/password" combination.
1. Shiro authentication process
1. Collect entity/credential information
Java code
- // Example using most common scenario of username/password pair:
- UsernamePasswordToken token = new UsernamePasswordToken (username, password );
- // "Remember Me" built-in:
- Token. setRememberMe (true );
UsernamePasswordToken supports the most common user name/password authentication mechanism. At the same time, because it implements the RememberMeAuthenticationToken interface, we can set the "remember me" function through the token.
However, "remembered" is different from "authenticated:
Only non-Anonymous Users are remembered. You can use subject. getPrincipals () to obtain user information. However, it is not a user who passes full authentication. When you access the function that requires user authentication, you still need to submit the authentication information again.
For the difference, refer to the Amazon website. The website will remember the logged-on users by default. When you access the website again, the page will display the remembered user information for non-sensitive page functions, however, you still need to perform logon authentication again when accessing the website account information.
2. Submit entity/credential information
Java code
- Subject currentUser = SecurityUtils. getSubject ();
- CurrentUser. login (token );
After the entity/credential information is collected, we can use the SecurityUtils tool class to obtain the current user, and then call the login method to submit the authentication.
3. Authentication Processing
Java code
- Try {
- CurrentUser. login (token );
- } Catch (UnknownAccountException uae ){...
- } Catch (IncorrectCredentialsException ice ){...
- } Catch (LockedAccountException lae ){...
- } Catch (ExcessiveAttemptsException family ){...
- }... Catch your own...
- } Catch (AuthenticationException AE ){
- // Unexpected error?
- }
If the login method is executed and no exception information is thrown, the user authentication is successful. Then, you can call SecurityUtils. getSubject () anywhere in the application to obtain the user instance that has passed the current authentication. Use subject. isAuthenticated () to determine whether the user has been verified, and return true.
On the contrary, if an exception is thrown during the execution of the login method, authentication fails. Shiro has a variety of distinctive exception classes to describe the cause of authentication failure, such as the sample code.
Ii. logout
You can call subject. logout () to delete your logon information, for example:
Java code
- CurrentUser. logout (); // removes all identifying information and invalidates their session too.
After the logout operation is completed, the Session information is cleared and the subject is regarded as an anonymous user.
Iii. Internal authentication processing mechanism
The above is the Shiro authentication process in the application. The following describes the Shiro authentication internal processing mechanism in detail.
For example, we use the Shiro architecture diagram to explain the internal processing sequence of Shiro certification:
1. The application constructs an AuthenticationToken instance for end user authentication information and calls the Subject. login method.
2. The Sbuject instance is generally an Instance Object of the DelegatingSubject class (or subclass). At the beginning of authentication, the securityManager instance set by the application is entrusted to call the securityManager. login (token) method.
3. When SecurityManager receives the token, it delegates the built-in Authenticator instance (usually an instance of the ModularRealmAuthenticator class) to the authenticator. authenticate (token ). modularRealmAuthenticator will adapt to one or more Realm instances in the authentication process. It actually provides a pluggable authentication mechanism for Shiro.
4. if multiple Realm instances are configured in the application, ModularRealmAuthenticator performs multi-Realm authentication based on the configured AuthenticationStrategy (authentication policy. After Realm is called, AuthenticationStrategy will respond to the result of each Realm.
NOTE: If only one Realm is configured in the application, the Realm will be called directly without configuring the authentication policy.
5. Determine whether each Realm supports the submitted token. If yes, Realm will call getAuthenticationInfo (token). The getAuthenticationInfo method is actually used for authentication, we can write custom authentication processing by overwriting the doGetAuthenticationInfo method of Realm.
4. Use multiple Realm processing mechanisms:
1. Authenticator
The default implementation is ModularRealmAuthenticator, which supports both single Realm and multiple Realm. If only one Realm is configured, ModularRealmAuthenticator will directly call this Realm to process authentication information. If multiple Realm instances are configured, It will adapt to Realm according to the authentication policy, find the appropriate authentication information for Realm execution.
Configure the User-Defined Authenticator:
Java code
- [Main]
- ...
- Authenticator = com. foo. bar. CustomAuthenticator
- SecurityManager. authenticator = $ authenticator
2. AuthenticationStrategy (Authentication Policy)
When multiple Realm instances are configured for an application, ModularRealmAuthenticator determines whether the authentication succeeds or fails Based on the authentication policy.
For example, if only one Realm instance is successfully verified, but other Realm instances fail to be verified, is the authentication successful? If most Realm verification is successful, is the authentication considered successful? Or, after a Realm is successfully verified, do you still need to judge the results of other Realm instances? The authentication policy is to make a decision on these issues based on the needs of the application.
An authentication policy is a stateless component that is called four times during the authentication process:
- Before all Realm calls
- Before calling the getAuthenticationInfo method of Realm
- After calling the getAuthenticationInfo method of Realm
- After all Realm instances are called
Another task of the authentication policy is to aggregate the result information of all Realm into an AuthenticationInfo instance and return this information as the identity information of Subject.
Shiro has three specific implementation of authentication policies:
AtLeastOneSuccessfulStrategy |
If one (or more) Realm authentication succeeds, authentication is considered successful. |
FirstSuccessfulStrategy |
If the first Realm is successfully verified, the overall authentication will be regarded as successful and the Realm will be ignored in the future. |
AllSuccessfulStrategy |
If all Realm instances are successful, authentication is considered successful. |
The default Implementation of ModularRealmAuthenticator's built-in authentication policies is the AtLeastOneSuccessfulStrategy method, which is also a widely used authentication policy. Of course, you can also define the policies you need through the configuration file, such:
Java code
- [Main]
- ...
- AuthcStrategy = org. apache. shiro. authc. pam. FirstSuccessfulStrategy
- SecurityManager. authenticator. authenticationStrategy = $ authcStrategy
- ...
3. Realm Sequence
From the authentication policy mentioned earlier, we can see that the order of Realm in ModularRealmAuthenticator has an impact on authentication.
ModularRealmAuthenticator reads the Realm configured in SecurityManager. If the authentication is performed, it traverses the Realm set and calls getAuthenticationInfo for all Realm instances that support token submission.
Therefore, if the order of Realm affects the authentication policy result, you should clearly define the order of Realm in the configuration file, such:
Java code
- BlahRealm = com. company. blah. Realm
- ...
- FooRealm = com. company. foo. Realm
- ...
- BarRealm = com. company. another. Realm
- SecurityManager. realms = $ fooRealm, $ barRealm, $ blahRealm