authentication , that is, in the application who can prove that he is himself. Generally provide identification information such as their identity ID to indicate that he is himself, such as providing ID card, username/password to prove.
In Shiro, the user needs to provide principals (identity) and credentials (proof) to Shiro so that the application can authenticate the user:
Principals: Identity, that is, the identity of the principal attribute, can be anything, such as user name, mailbox, etc., the only thing. A subject can have multiple principals, but only one primary principals, usually username/password/mobile number.
credentials: proof/credential, that is, only the principal knows the security value, such as password/digital certificate.
The most common combination of principals and credentials is the username/password. The next step is to start with a basic identity certificate.
The other two related concepts are the Subject and Realmspreviously mentioned, which are the data sources of the subject and the verification subject respectively.
2.2 Environment Preparation
This article uses MAVEN to build and therefore requires a bit of maven knowledge. First prepare environment dependent: Java code <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version> </dependency> <dependency> <groupid>org.apache.shiro</groupid> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </ dependency> </dependencies>
Add JUnit, common-logging, and Shiro-core dependencies.
2.3 Login/Exit
1, first prepare some user identity/credentials (Shiro.ini) Java code [users] zhang=123 wang=123
The INI configuration file is used here and two principals are specified through [users]: zhang/123, wang/123.
2. Test case (com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest) Java code @Test Public void testhelloworld () { //1, get SecurityManager factory, Use INI config file here to initialize securitymanager Factory< org.apache.shiro.mgt.securitymanager> factory = new inisecuritymanagerfactory ("Classpath:shiro.ini"); &NBSP;&NBSP;&NBSP;&NBSP;//2, get SecurityManager instance and bind to securityutils Org.apache.shiro.mgt.securitymanager securitymanager = factory.getinstance (); securityutils.setsecuritymanager (SecurityManager); &NBSP;&NBSP;&NBSP;&NBSP;//3, Get Subject and create username/password Authentication tokens (i.e. user identity/credentials) Subject subject = Securityutils.getsubject (); &nbsP Usernamepasswordtoken token = new usernamepasswordtoken ("Zhang", "123"); try { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//4, Login, authentication subject.login (token); } catch (authenticationexception e) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;//5, authentication failure } assert.assertequals (true, subject.isauthenticated ()); //asserts that the user is logged in &NBSP;&NBSP;&NBSP;&NBSP;//6, Exit subject.logout (); }
2.1, first through the new inisecuritymanagerfactory and specify an INI configuration file to create a SecurityManager factory;
2.2, then get SecurityManager and bind to Securityutils, this is a global setting, set once;
2.3, through securityutils get subject, it will automatically bind to the current thread, if the Web environment needs to unbind at the end of the request, and then get the token of authentication, such as username/password;
2.4, call the Subject.login method to log in, it will automatically delegate to the Securitymanager.login method to log in;
2.5, if authentication fails to capture authenticationexception or its subclasses, common such as: Disabledaccountexception (Disabled account), Lockedaccountexception (Locked account), Unknownaccountexception (Bad account number), excessiveattemptsexception (too many login failures), incorrectcredentialsexception (bad credentials), Expiredcredentialsexception (expired vouchers), such as, see the inheritance relationship, for the page error message display, it is best to use such as "username/password Error" instead of "User name error"/"Password error", to prevent some malicious users to illegally scan the account base;
2.6, finally can call Subject.logout exit, it will automatically delegate to the Securitymanager.logout method exit.
you can summarize the steps of authentication from the above code:
1, the collection of user identity/credentials, such as user name/password;
2, call Subject.login to log in, if the failure will get the corresponding authenticationexception exception, according to the exception prompt user error message;
3, the last call Subject.logout to exit the operation.
Several issues as tested above:
1, the user name/password hard-coded in the INI configuration file, later need to change to such as database storage, and password needs to encrypt storage;
2, the user identity token may be not only the user name/password, there may be other, such as login to allow the user name/mailbox/Mobile phone number at the same time login.
2.4 Identity Verification process
The process is as follows:
1, first call Subject.login (token) to log in, it will be automatically delegated to the security Manager, the call must pass through Securityutils. Setsecuritymanager () setting;
2. SecurityManager is responsible for the real authentication logic; It will delegate authentication to authenticator;
3, authenticator is the real authenticator, Shiro API in the core authentication entry point, where you can customize to insert their own implementation;
4, authenticator may entrust to the corresponding authenticationstrategy for multi-realm authentication, The default modularrealmauthenticator will call Authenticationstrategy for multiple realm authentication;
5, authenticator will send the corresponding token into realm, obtain authentication information from realm, if no return/Throw exception indicates authentication failed. Multiple realms can be configured here and will be accessed in the appropriate order and policy.
2.5 Realm
Realm: Shiro from the realm to obtain security data (such as users, roles, permissions), that is, SecurityManager to verify the identity of the user, then it needs to get the appropriate user from realm to compare to determine whether the user identity is legitimate It also requires the user's corresponding roles/privileges from realm to verify that the user is able to operate, and that realm can be viewed as a DataSource, a secure data source. As in our previous INI configuration, we will use Org.apache.shiro.realm.text.IniRealm.
The Org.apache.shiro.realm.Realm interface is as follows: Java code String getName (); Returns a unique realm name, Boolean supports (Authenticationtoken token); Determine if this realm supports this token authenticationinfo getauthenticationinfo (Authenticationtoken token) throws Authenticationexception; Obtain certification information based on token
Single Realm configuration
1. Custom realm Implementation (COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM1): Java code public class myrealm1 implements realm { @Override public string getname () { return "MYREALM1"; } @Override public boolean supports (authenticationtoken Token) { //only supports usernamepasswordtoken types of tokens return token instanceof usernamepasswordtoken; } @Override public authenticationinfo getauthenticationinfo ( Authenticationtoken token) &NBsp;throws authenticationexception { string username = (String) Token.getprincipal (); //get username string password = new string ((char[]) Token.getcredentials ()); //Get password if (! ") Zhang ". Equals (username)) { throw new unknownaccountexception (); //if user name error } if (! " 123 ". Equals (password)) { throw new incorrectcredentialsexception (); //if password error } &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBsp; //If authentication is successful, return a AuthenticationInfo implementation; return new simpleauthenticationinfo (Username, password, getname ()); } }
2. ini configuration file specifies custom realm implementation (Shiro-realm.ini) Java code #声明一个realm myrealm1= COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM1 #指定securityManager的realms实现 securitymanager.realms=$ MyRealm1
Using $name to introduce the previous realm definition
3. For the test case, refer to Com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest's Testcustomrealm test method, just change the previous Shiro.ini configuration file to Shiro-realm.ini.
Multi-Realm configuration
1. ini configuration file (Shiro-multi-realm.ini) Java code #声明一个realm myrealm1=com.github.zhangkaitao.shiro.chapter2.realm.myrealm1 m YREALM2=COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM2 #指定securityManager的realms实现 securitymanager.realms= $myRealm 1, $myRealm 2
SecurityManager will authenticate in the order specified by realms. Here we specify the order of realms in the specified order, and if you delete "securitymanager.realms= $myRealm 1, $myRealm 2", Then the SecurityManager will be used in the order of realm declarations (that is, without setting the Realms property, it will be automatically discovered), and when we display the specified realm, the other unspecified realms will be ignored, such as " securitymanager.realms= $myRealm 1 ", then MYREALM2 will not be automatically set in.
2, test case please refer to com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest Testcustommultirealm test method.
Shiro the realm provided by default
You can inherit Authorizingrealm (authorization) Later, inherit Authenticatingrealm (that is, authentication), and indirectly inherit the Cachingrealm (with the cache implementation). The main default implementations are as follows:
Org.apache.shiro.realm.text.IniRealm: [Users] section specifies the user name/password and its role; [Roles] section specifies the role as permission information;
Org.apache.shiro.realm.text.PropertiesRealm: user.username=password,role1,role2 Specify user name/password and its role; role.role1 =permission1,permission2 Specify role and permission information;
Org.apache.shiro.realm.jdbc.JdbcRealm: Query the appropriate information through SQL, such as "Select password from users where username =?" Get the user password, "Select Password, password_salt from users where username =?" Get the user's password and salt; "Select Role_name from user_roles where username =?" Get the user role; "SELECT permission from roles_permissions where role_name =?" Gets the permission information for the role, or invokes the appropriate API for custom SQL;
JDBC Realm uses
1. Database and dependent Java code <dependency> <groupId>mysql</groupId> <artifactid>mysql-connector-ja va</artifactid> <version>5.1.25</version> </dependency> <dependency> <gro Upid>com.alibaba</groupid> <artifactId>druid</artifactId> <version>0.2.23</versi On> </dependency>
This article will use MySQL database and Druid connection pool;
2, to the database Shiro three tables: Users (user name/password), user_roles (user/role), Roles_permissions (role/permissions), please refer to shiro-example-chapter2/sql/ Shiro.sql; and add a user record, username/password for zhang/123;
3. INI configuration (shiro-jdbc-realm.ini) Java code Jdbcrealm=org.apache.shiro.realm.jdbc.jdbcrealm datasource= Com.alibaba.druid.pool.DruidDataSource datasource.driverclassname=com.mysql.jdbc.driver DATASOURCE.URL=JDBC: Mysql://localhost:3306/shiro datasource.username=root #dataSource. password= jdbcrealm.datasource= $dataSource secur itymanager.realms= $jdbcRealm
1. Variable name = Fully qualified class name automatically creates an instance of a class
2. Variable name. property = value automatically calls the appropriate setter method to assign the value
3, $ variable name refers to an object instance before
4, the test code please refer to Com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest Testjdbcrealm method, and the previous no difference.
2.6 Authenticator and Authenticationstrategy
Authenticator's role is to authenticate the user account, which is the entry point for the authentication core in the Shiro API: Java code public authenticationinfo authenticate (Authenticationtoken Authenticationtoken) throws Authenticationexception;
If the validation succeeds, the AuthenticationInfo authentication information is returned, the identity and credentials are included in the message, and the corresponding Authenticationexception implementation is thrown if the validation fails.
The SecurityManager interface inherits the authenticator, and another modularrealmauthenticator implementation, which is delegated to multiple realms for verification, Validation rules are specified by the Authenticationstrategy interface, which provides the implementation by default:
firstsuccessfulstrategy: As long as there is a realm verification success, only the first realm authentication successfully authenticated information, other ignored;
atleastonesuccessfulstrategy: As long as there is a realm verification success, and Firstsuccessfulstrategy different, return all realm authentication authentication information successfully;
allsuccessfulstrategy: All Realm verification success is successful, and return all realm authentication successful authentication information, if one failure fails.
Modularrealmauthenticator uses the Atleastonesuccessfulstrategy policy by default.
Let's say we have three realms:
MYREALM1: The username/password is zhang/123, and the return identity/credential is zhang/123;
MYREALM2: The username/password is wang/123, and the return identity/credential is wang/123;
MYREALM3: The username/password is zhang/123 when successful, and the return identity/credential is zhang@163.com/123, and MYREALM1 different is the identity changed when returning;
1. ini configuration file (Shiro-authenticator-all-success.ini) Java code #指定securityManager的authenticator实现 authenticator= Org.apache.shiro.authc.pam.ModularRealmAuthenticator securitymanager.authenticator= $authenticator # Specifies the authenticationstrategy of the Securitymanager.authenticator allsuccessfulstrategy= Org.apache.shiro.authc.pam.AllSuccessfulStrategy securitymanager.authenticator.authenticationstrategy=$ Allsuccessfulstrategy Java code MYREALM1=COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM1 myRealm2= COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM2 myrealm3= COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.REALM.MYREALM3 securitymanager.realms= $myRealm 1, $myRealm 3
2. Test code (COM.GITHUB.ZHANGKAITAO.SHIRO.CHAPTER2.AUTHENTICATORTEST)
2.1. First Universal login Logic Java code private void login (string configfile) { &NBSP;&NBSP;&NBSP;&NBSP;//1, get SecurityManager factory, use INI configuration file to initialize securitymanager Factory<org.apache.shiro.mgt.SecurityManager> factory = new inisecuritymanagerfactory (ConfigFile); &NBSP;&NBSP;&NBSP;&NBSP;//2, get SecurityManager instances and bind to securityutils org.apache.shiro.mgt.securitymanager securitymanager = factory.getinstance (); securityutils.setsecuritymanager (SecurityManager); &NBSP;&NBSP;&NBSP;&NBSP;//3, get Subject and create username/password Authentication token (i.e. user identity/credentials) subject subject = securityutils.getsubject (); usernamepasswordtoken token&nbSp;= new usernamepasswordtoken ("Zhang", "123"); Subject.login (token); }
2.2. Test Allsuccessfulstrategy Success: Java code @Test public void Testallsuccessfulstrategywithsuccess () {<