A preface
This article is about the use of Shiro authority framework, of course, knowledge seekers will not hand hand fool code to you, but first let you understand the core of authority is what Shiro authority authentication process, combined with the core code to show the way to everyone;
Public account: Knowledge seeker
Inheriting the spirit of open Source, Spreading technology knowledge;
Shio certification process
2.1 Introduction to Authentication and Authorization
First of all, it should be emphasized that the core function of each authorization framework is authentication, authorization, and if the reader has two concepts, it will be very easy to learn the knowledge related to permissions;
Simple said the certification, certification is a message to the service end, you this piece of information server received will follow before your registration information, such as in the case of without any encryption will account, password input form form sends a request to the server, the server according to compare the before you register account password, if success, that authentication is successful, Otherwise, the authentication fails. Complex certification would be to your account, password is another kind of form is usually called encapsulate certificate, signature and so on, the document of this form sent to you again, then every request you bring proof and end according to you send confidential information decrypted, success means that authentication is successful, otherwise the authentication failure;
Simply under authorization, design basic permissions are now based on user roles, permissions way to carry on the design, so what a user has permissions are based on what kind of role, we can give each role different permissions, and then certification after successful can accredit to the user (namely the user has the role of, Permission to return out ok, each request with the permission information, the server then according to the attached permission information to distinguish);
2.2 Main concept and structure of Shiro
- Subject The current Subject, which you can interpret as the current user;
- SecurityManag: principal manager, which simply manages a lot of user information;
- Authenticator: authenticates when you log in or send a request.
- Authorizer: Authorizer: Authorizer: Authorizer: Authorizer
- SessionManager: SessionManager,
- CacheManager: CacheManager
- Cryptography: suitable for enterprise-level development, providing algorithmic encryption;
- Realms: is a bridge between Shio and your app’s all-secure data; Authentication and authorization will be carried out on this side;
Shiro features the following, which is the chunking of the above content
The introduction of more information see the website: www.infoq.com/articles/ap…
2.3 Shiro certification process
The general certification process is as follows; We intercept the request, send the request information through the Security Manager to the Realm for authentication and authorization, and send the request to the server. The server encapsulates the data and sends it back to the front end. Ok is easy;
Three Springboot integration shiro
This integration solution is to follow the official steps to replace the entire XML bean with Java annotations; Interested readers check out the official website
shiro.apache.org/spring.html
3.1 the pom. XML
In this writing process, the knowledge seeker ignores the operation of table building. It is easy for readers to realize it if they know how to think.
>mybatis-spring-boot-starter >mybatis-spring-boot-starter The key is to introduce Shiro core dependencies
<dependencies>
<! -- MyBatis -->
<! -- <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> The < version > 1.3.1 < / version > < / dependency > -- >
<! --web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<! -- Shiro core dependencies -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Copy the code
3.2 Shiro configuration is as follows
- ShiroFilterFactoryBean is a configuration interceptor, the user intercepts the URL, anno means anonymous, any user can access; Authc indicates authorization, which requires the user with authorization information to access,
- The SecurityManager is the principal manager that manages many principals and needs to inject our implementations into them for authentication and authorization.
- ShiroRealm injects HashedCredentialsMatcher, which is where the credentials are generated. The encryption is the same as when the user is registered, otherwise authentication will fail in Realm.
- AuthorizationAttributeSourceAdvisor, APO support, is primarily need to use @ RequiresRoles, @ RequiresPermissions annotation works;
- LifecycleBeanPostProcessor, Shiro bean lifecycle, see website mean AuthorizationAttributeSourceAdvisor implementation based on the line,
/ * * *@Author lsc
* <p> </p>
*/
@Configuration
public class ShiroConfiguration {
// http://shiro.apache.org/spring.html
// Shiro authorizes interception
@Bean
public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// Create a map and configure interception information
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// Anonymous user accessible
filterChainDefinitionMap.put("login/**"."anon");
filterChainDefinitionMap.put("register/**"."anon");
// Authenticate user access
filterChainDefinitionMap.put("/ * *"."authc");
/ / login url
shiroFilterFactoryBean.setLoginUrl("/user/unauth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/* * * @author LSC * Manage multiple subject
* @param [] */
@Bean
public SecurityManager securityManager(a) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(Realm());
return securityManager;
}
/* * * @author LSC * Authentication information
* @param [] */
@Bean
public ShiroRealm Realm(a) {
// The authentication and authorization class that we implement
ShiroRealm realm = new ShiroRealm();
// The encryption Settings are configured here, and the way to create the password when the user logs in must be consistent
realm.setCredentialsMatcher(hashedCredentialsMatcher());
return realm;
}
/* * * @author LSC * * @param [] */
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(a) {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// Use MD5 encryption
hashedCredentialsMatcher.setHashAlgorithmName("md5");
// Loop encryption twice
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
/* * * @author LSC * Enable shiro-AOP annotation support, such as @requiresRoles, @requirespermissions, * It depends on shiro lifecycle
* @param [securityManager] */
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/ * * * @ Author LSC * < p > < / p > * @ shiro lifecycle Param [] * /
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanProcessor(a) {
return newLifecycleBeanPostProcessor(); }}Copy the code
3.3 ShiroRealm
ShiroRealm implements AuthorizingRealm, which AuthenticationInfo method; AuthorizationInfo method, code steps are very complete, not too much explanation;
/ * * *@Author lsc
* <p> </p>
*/
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private SysUserService userService;
// Simply override the method to get authorization information
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// Obtain authorization information
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// Get the user
SysUserEntity userEntity = (SysUserEntity) principalCollection.getPrimaryPrincipal();
// Obtaining role rights through user-role-rights association is omitted
/ /...
// Put the role's permissions into the collection
Set<String> rolesSet = new HashSet<>();
// Put the permission information into the collection
Set<String> permsSet = new HashSet<>();
// Permission authorization
simpleAuthorizationInfo.setStringPermissions(permsSet);
// Role authorization
simpleAuthorizationInfo.setRoles(rolesSet);
return simpleAuthorizationInfo;
}
// Shiro obtains authentication information, that is, obtains the password, salt, etc. from the database based on the user name in the token and returns it
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// Get the user name
String userName = token.getPrincipal().toString();
// Query the encrypted password
SysUserEntity user = userService.getUserByUserName(userName);
String password= user.getPassword();
/ / salt value
String salt = user.getSalt();
// Verify
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, ByteSource.Util.bytes(salt), getName());
// The certificate is passed
returnauthenticationInfo; }}Copy the code
3.4 Register in the login method
Securityutils.getsubject (); Get the main user information, pass the username and password to UsernamePasswordToken and call subject.login(UsernamePasswordToken). It’s going to go to realm for authentication;
Real_realm () : real_realm () : real_realm () : real_realm () : real_realm () : real_realm ()
@Autowired
SysUserService sysUserService;
@PostMapping(value = "login")
public ResponseEntity login(@RequestBody SysUserEntity sysUserEntity) {
String username = sysUserEntity.getUsername();
Subject subject = SecurityUtils.getSubject();
/ / shiro certification
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, sysUserEntity.getPassword());
// JWT integrates Shiro authentication
SysUserEntity user = sysUserService.getUserByUserName(username);
Map map = new HashMap();
if (user==null){
System.out.println("User name cannot be empty");
/ / thrown exception
}
try {
// Shiro authentication authentication
subject.login(usernamePasswordToken);
map.put("name",user.getName());
} catch (AuthenticationException e) {
System.out.println("Authentication failed"+e.getMessage());
}
return ResponseEntity.ok(map);
}
@PostMapping("register")
public ResponseEntity unauth(@RequestBody SysUserEntity sysUserEntity){
SysUserEntity userByUserName = sysUserService.getUserByUserName(sysUserEntity.getUsername());
if(userByUserName! =null){
System.out.println("User name cannot be empty");
/ / thrown exception
}
// Encryption mode
String hashAlgorithmName = "MD5";
String credentials = sysUserEntity.getPassword();
// Encryption times
int hashIterations = 2;
// Generate salt, default length 16 bits
String salt = new SecureRandomNumberGenerator().nextBytes().toString();
ByteSource credentialsSalt = ByteSource.Util.bytes(salt);
// Encrypted password
SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials, credentialsSalt, hashIterations);
// Set the encrypted password
sysUserEntity.setPassword(simpleHash.toString());
/ / set the salt
sysUserEntity.setSalt(salt);
/ / r into the Treasury
sysUserService.addSysUser(sysUserEntity);
return ResponseEntity.ok(sysUserEntity);
}
Copy the code
Focus on knowledge seekers: