shiro function and basic knowledge
shiro mainly has two parts, one is authentication, the other is authorization
- Authentication: when a user logs in to the system, shiro will authenticate whether the user is a logged in user.
- Authorization: a system can have users in several roles, such as administrators or ordinary users. How to define administrators and ordinary users? This requires the authorization mechanism in shiro to assign different role permissions to users
Basic knowledge and process of certification
1. Key objects of authentication in shiro
- **Subject: * * the subject is the user accessing the system. The subject enables the user, program and user to authenticate, which is called the subject.
- **Principal: * * identity information basically refers to the user name or other information, but the identity information must be unique.
- **Credential: * * credential information, which is only the security information known by the subject, such as password, certificate, etc
2. Certification process
Shiro will package the identity information and credential information into a Token and go to the security manager in the core architecture of Shiro to verify whether it is legal. If the information is consistent, you can enter the system. If it is inconsistent, the authentication fails.
3. Specific operation
Introducing shiro's dependency
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency>
Profile for introducing shiro
This is a * ini file. * ini file is similar to txt file. ini file can write some complex data formats. This configuration file should be placed in the resources folder of maven file. Used to learn shiro to write relevant permission data of our system. Put the permission data into the ini configuration file without directly connecting to the database
[users] # user 'root' with password 'secret' and the 'admin' role root = secret, admin # user 'guest' with the password 'guest' and the 'guest' role guest = guest, guest # user 'presidentskroob' with password '12345' ("That's the same combination on # my luggage!!!" ;)), and role 'president' presidentskroob = 12345, president # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz' darkhelmet = ludicrousspeed, darklord, schwartz # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz' lonestarr = vespa, goodguy, schwartz # Automatically added information xiaochen=123 # ----------------------------------------------------------------------------- # Roles with assigned permissions # # Each line conforms to the format defined in the # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc # ----------------------------------------------------------------------------- [roles] # 'admin' role has all permissions, indicated by the wildcard '*' admin = * # The 'schwartz' role can do anything (*) with any lightsaber: schwartz = lightsaber:* # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with # license plate 'eagle5' (instance specific id) goodguy = winnebago:drive:eagle5
Add some fixed content to the configuration file
In the previous step, we added shiro's configuration file. We can add our own information in the configuration file.
Example: in the figure below, xiaochen=123 means that the user name is xiaochen and the password is 123. You can log in to our system.
It is equivalent to writing some user names and passwords in the configuration file and allowing them to pass shiro's permissions.
(tip: This is only a part of shiro's process. Later, we will directly connect to the database to obtain the user name and password of the database)
Write the main method to test shiro's function
The process of this method is the process that shiro needs to operate for authentication. Note that the realm here is the original relay inirealm
package com.example.shiro.demoshiro; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; //Test shiro's function public class TestAuthenticator { public static void main(String[] args){ // 1. Create a security manager object DefaultSecurityManager securityManager=new DefaultSecurityManager(); // 2. Set realm to the security manager and read Shiro Ini configuration file securityManager.setRealm(new IniRealm("classpath:shiro.ini")); // 3. The global tool class, securityUtils, provides authentication and exit methods // Set the security manager for the tool class of global security SecurityUtils.setSecurityManager(securityManager); // 4. Get the subject of the key object Subject subject = SecurityUtils.getSubject(); // 5. Create a token, create an object of user password token, and assign a value UsernamePasswordToken token = new UsernamePasswordToken("xiaochen","123"); // 6. Perform user authentication and output a plurality of exception information try{ System.out.println("Certification status:"+subject.isAuthenticated());//Get authentication status information subject.login(token); //User authentication System.out.println("Certification status:"+subject.isAuthenticated()); }catch(UnknownAccountException e){ e.printStackTrace();//Print exception information System.out.println("Authentication failed, user does not exist"); }catch(IncorrectCredentialsException e) { e.printStackTrace();//Print exception information System.out.println("Authentication failed, user information error"); }catch(Exception e){ e.printStackTrace();//Print exception information } } }
4. Read the information in the database
In 3, we introduced shiro's configuration file shiro Ini, user name and password are all set here, but when we really use shiro, we need the information stored in the database, so it is inevitable that we use shiro to connect to the database.
1. Theoretical analysis of source code
First, we can implement it through realm. Does our data come from the database or ini configuration file.
Through the source code, we found:
Finally, the user name verification is completed in the doGetAuthenticationInfo method under the simpleAccountRealm class that performs user name comparison. This simpleAccountRealm inherits the authorizing realm class. If we write a class to change it to the database as verification data, we also need to create a new class to inherit the authorizing realm class.
The final password verification is completed in the assertCredentialsMatch method in the AuthenticatingRealm class. It's done automatically.
2. Customize the realm class connecting to the database
The custom Realm class inherits the doGetAuthenticationInfo method in the authorizingream class implementation to redefine the source path of authentication. Here is the data changed to the database, and the doGetAuthorizationInfo () method is used for authorization
package com.example.shiro.realm; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; /** * This class is customized, and the Realm converts the authenticated or authorized data source into a database */ public class CustomerRealm extends AuthorizingRealm { // Method of authorization @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } // Method of authentication @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //Get user name in token String principal = (String) authenticationToken.getPrincipal(); System.out.println(principal); // According to the identity information, use jdbc or mybatis to query the relevant database. Here, use fake data for verification // Originally, an AuthenticationInfo object should be returned, which uses the implementation class simpleAuthenticationInfo of this class if("xiaochen".equals(principal)){ // Parameter 1: returns the correct user name in the database; parameter 2: returns the correct password in the database; parameter 3: provides the name of the current realm this Getname(), which can be implemented by this method. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("xiaochen","123",this.getName()); return simpleAuthenticationInfo; } return null; } }
3. Write the main method to test the realm
package com.example.shiro.demoshiro; import com.example.shiro.realm.CustomerRealm; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; /** * Use the custom realm test class. The custom realm class is used here, so you don't have to use the in the ini configuration file */ public class TestCustomerRealmAuthentictor { public static void main(String[] args) { // Create securityManager DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); // Set our ream defaultSecurityManager.setRealm(new CustomerRealm()); // Set the security tool class to the security manager SecurityUtils.setSecurityManager(defaultSecurityManager); // Obtain the subject through the security tool class Subject subject = SecurityUtils.getSubject(); // Create token UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123"); try { subject.login(token); System.out.println(subject.isAuthenticated());//Print verification status } catch (AuthenticationException e) { e.printStackTrace(); } } }