Shiro permission framework (II)
In the previous chapter, we learned the simple structure of Shiro framework and two important methods. Next, we will learn how to use the authentication and authorization of the framework.
Custom Realm
Generally, our user name and password data are from the database, so it is very necessary to customize the real to read the data in the database.
According to our process analysis, our customized Realm should inherit the class authoringrealm and override two methods:
- Dogetauthenticationinfo() authentication
- doGetAuthorizationInfo() authorization
Authentication - dogetauthenticationinfo()
Code implementation:
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // Get user name String principal = (String) authenticationToken.getPrincipal(); System.out.println(principal); // Start to query the password corresponding to the user name in the database according to the user name. if ("xiaocheng".equals(principal)){ // The data here is used for the data obtained by connecting to the database // SimpleAuthenticationInfo inherits from AuthenticationInfo // AuthenticationInfo saves the basic information of the correct user // Parameter 1: user name parameter 2: password parameter 3: current realm name (this.getName()) return new SimpleAuthenticationInfo(principal, "123", this.getName()); } return null; }
MD5 + salt encryption
Sometimes we can't save the user's password in plaintext in the database. We need to encrypt it.
You also need to customize the Realm.
MD5 encryption
doGetAuthenticationInfo() of Realm:
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // Get user name String principal = (String) authenticationToken.getPrincipal(); // Query database comparison if (principal.equals("xiaocheng")){ // md5 return new SimpleAuthenticationInfo(principal,"202cb962ac59075b964b07152d234b70",this.getName()); } return null; }
test:
// Custom realm uses CustomMd5Realm md5realm CustomMd5Realm realm = new CustomMd5Realm(); // Create a hash credential authenticator. Password authentication uses -- > hashedcredentialsmatcher, which is a subclass of SimpleCredentialsMatcher. If hash is used, it is a simple equals comparison. HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); // Using md5 algorithm hashedCredentialsMatcher.setHashAlgorithmName("md5"); // Set realm to use hash credential matcher realm.setCredentialsMatcher(hashedCredentialsMatcher);
Since then, an md5 encryption authenticator has been added to the custom realm. When matching subject s, users will be matched according to the matcher.
md5 + salt
doGetAuthenticationInfo() of Realm:
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // Get user name String principal = (String) authenticationToken.getPrincipal(); // Query database comparison if (principal.equals("xiaocheng")){ // md5 + salt // Parameter 3: salt, with the help of bytesource Util. Bytes() completes the salt adding operation return new SimpleAuthenticationInfo(principal,"cc1e39955047cba6c751ad1a6214af26",ByteSource.Util.bytes("salt"),this.getName()); } return null; }
test:
// Custom realm uses CustomMd5Realm md5realm CustomMd5Realm realm = new CustomMd5Realm(); // Create a hash credential authenticator. Password authentication uses -- > hashedcredentialsmatcher, which is a subclass of SimpleCredentialsMatcher. If hash is used, it is a simple equals comparison. HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); // Using md5 algorithm hashedCredentialsMatcher.setHashAlgorithmName("md5"); // Set hash times hashedCredentialsMatcher.setHashIterations(1024); // Set realm to use hash credential matcher realm.setCredentialsMatcher(hashedCredentialsMatcher);
The salting process adds parameters to the return value in doGetAuthenticationInfo(), but the salting process uses a tool class bytesource Utile. bytes("salt").
md5 + salt + hash hash
doGetAuthenticationInfo() of Realm:
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // Get user name String principal = (String) authenticationToken.getPrincipal(); // Query database comparison if (principal.equals("xiaocheng")){ // md5 + salt + hash return new SimpleAuthenticationInfo(principal,"d10ce44fb96e787ef5a57c1aed5da166",ByteSource.Util.bytes("salt"),this.getName()); } return null; }
test:
// Custom realm uses CustomMd5Realm md5realm CustomMd5Realm realm = new CustomMd5Realm(); // Create a hash credential authenticator. Password authentication uses -- > hashedcredentialsmatcher, which is a subclass of SimpleCredentialsMatcher. If hash is used, it is a simple equals comparison. HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); // Using md5 algorithm hashedCredentialsMatcher.setHashAlgorithmName("md5"); // Set hash times hashedCredentialsMatcher.setHashIterations(1024); // Set realm to use hash credential matcher realm.setCredentialsMatcher(hashedCredentialsMatcher);
Set hash times when setting authentication credentials
Summary
All use hash credential authenticator = = > hashedcredentialsmatcher
- md5 encryption: hashedcredentialsmatcher Sethashalgorithmname ("md5") occurs on the authenticator.
- md5 + salt encryption: return simpleauthenticationinfo (principal, "password", bytesource.util.bytes ("salt"), this Getname()) occurs on the custom Realm.
- md5 + salt + hash encryption: hashedcredentialsmatcher Sethashiterations (1023) occurs on the authenticator.
Reasonable use of encryption can make our authentication more secure. In this section, you need to know where the encryption operations are specific, not in the authenticator. The salt adding operation is completed in real. After passing the certification, you should go to the next step - authorization
Authorization - doGetAuthorizationInfo()
When the user is authenticated as a legal user, it enters the authorization process.
In fact, authorization is to specify who operates what resources.
Each legal user has its own permissions in the current project, which are bound with resources.
Authorization method
The mainstream authorization methods are divided into two rbacs:
-
Role based access control
Each role is divided into permissions, that is, users will be assigned roles, and each role can only access its permission range. -
Resource based access control
Take resources as the core for access control, and specify who can operate resources and how to operate them.
Permission string
The rules for permission strings are: Resource Identifier: Action: resource instance identifier
example:
- User creation permission: user:create or user:create:*
- User's permission to modify instance test: user:update:test
- All permissions of user operation test: user:*:test
Wildcards can be used*
Authorization implementation
In the custom Realm, we implemented the doGetAuthenticationInfo() method to authenticate, and another doGetAuthoriztionInfo() is used for authorization.
So we need to complete the authorization in this method.
When a user requests authorization, you need to query the specific permissions of the user in the database to complete the authorization.
Realm configuration:
// Authorization configuration @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { // Print user's main color String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal(); System.out.println("user name:"+primaryPrincipal); // Create authorization information - AuthorizationInfo. You can use SimpleAuthorizationInfo SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); // Assign the role information queried in the database to the permission object simpleAuthorizationInfo.addRole("admin"); simpleAuthorizationInfo.addRole("user"); // Assign the permission information queried in the database to the permission object simpleAuthorizationInfo.addStringPermission("admin:*"); simpleAuthorizationInfo.addStringPermission("user:create"); return simpleAuthorizationInfo; }
Request authorization:
// Certification passed if (subject.isAuthenticated()){ // 1. Role based permission control System.out.println(subject.hasRole("admin")); // Query whether the principal has the role of admin // 2. Multi role permission control boolean b = subject.hasAllRoles(Arrays.asList("admin","user")); // Query whether the principal has the roles of admin and user. If not, false is returned System.out.println(b); // 3. View the roles of the entity boolean[] booleans = subject.hasRoles(Arrays.asList("admin", "super", "user")); for (boolean aBoolean : booleans) { System.out.println(aBoolean); } System.out.println("================Access control based on permission string================"); // 4. Access control resource identifier based on permission string: operation: resource type // Check whether the principal has the permission to create the 001 resource under admin System.out.println(subject.isPermitted("admin:create:001")); // Query whether the entity has permission for "admin:create: *" and "user:*:001" respectively boolean[] permitted = subject.isPermitted("admin:create:*", "user:*:001","user:create:002"); for (boolean b1 : permitted) { System.out.println(b1); } // Check whether the principal has permissions at the same time System.out.println(subject.isPermittedAll("admin:create:*", "user:update:001","user:create:002")); }
Summary
This chapter learned the use of authentication and authorization methods in user-defined Realm inheritance authoringrealm. There is also data encryption in the authentication process. Next, we will learn how to use Spring Boot combined with database integration Shiro.