A day to learn Shiro
Referring to markerHub's open source project, you can take a look and I think the whole development process is complete.
Basically it was written in reference to an open source project. I am not very familiar with this part. Even though I have read the theory tutorial, I am not very able to write it out, so I imitated it.
Step 1: Import the starter package of shiro-redis into the pom file: There is also a jwt toolkit to simplify development and a hutool toolkit to introduce.
Hutool exists to reduce code search costs and avoid bug s caused by uneven code on the network.
<dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis-spring-boot-starter</artifactId> <version>3.2.1</version> </dependency> <!-- hutool Tool class--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.3.3</version> </dependency> <!-- jwt --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
Step 2: Rewrite your SessionManager or SessionsSecurityManager.
RedisSessionDAO and RedisCacheManager were introduced to enable session sharing in order to save shiro's privilege data and session information to redis.
package com.hotin.server.config; import org.apache.shiro.mgt.SessionsSecurityManager; import org.apache.shiro.realm.Realm; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; /** * @author :hotin * @date :2021/11/22 19:20 */ @Configuration public class ShiroConfig { @Bean public SessionManager sessionManager(RedisSessionDAO redisSessionDAO) { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); // inject redisSessionDAO sessionManager.setSessionDAO(redisSessionDAO); // other stuff... return sessionManager; } @Bean public SessionsSecurityManager securityManager(List<Realm> realms, SessionManager sessionManager,RedisCacheManager redisCacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realms); //inject sessionManager securityManager.setSessionManager(sessionManager); // inject redisCacheManager securityManager.setCacheManager(redisCacheManager); // other stuff... return securityManager; } }
Step 3: Define your own AccountRealm, the above method is for authentication, and the following method is for authorization, remember to add the Component annotation and inject it into the container.
- Realm: Usually we all need to implement our own Realm. We can have one or more Realms, which are the sources of secure data (account number/password) that we get when we authenticate to log in.
package com.hotin.server.config.shiro; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; /** * @author :hotin * @date :2021/11/22 19:49 */ @Component public class AccountRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { return null; } }
Step 3: Replace your AccountRealm with the Realm of ShiroConfig
@Bean public SessionsSecurityManager securityManager(AccountRealm accountRealm, SessionManager sessionManager, RedisCacheManager redisCacheManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(accountRealm); //inject sessionManager securityManager.setSessionManager(sessionManager); // inject redisCacheManager securityManager.setCacheManager(redisCacheManager); // other stuff... return securityManager; }
Now the hierarchical catalog diagram, I like to separate components from configuration classes so that I can quickly find components that change business logic
Error will occur if you start now
Next, we'll add ShirofilterChainDefinitions and ShiroFilterFactoryBean.
When the project starts, shrio uses its own org.apache.shiro.spring.web.ShiroFilterFactoryBean class's
The filterChainDefinitions property is converted to a filterChainDefinitionMap after the transformation is complete
Deliver to ShiroFilterFactoryBean for safekeeping.
FiltererChainDefinitions specifies the filtering rules. General public configurations use configuration files, such as jss css img, which are not intercepted. The URLs of related businesses are configured to the database, and the filters query the database for permission judgment.
shiro's own filter
anon: Access without authentication
authc: Authentication is required to access
user: click on the "Remember Me" feature to access
perms: Permission to access
Role: Has a role permission to access
@Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/**", "authc"); // Verify permissions mainly through annotations // Change to shiro's own authc filter to test whether it started properly chainDefinition.addPathDefinitions(filterMap); return chainDefinition; } @Bean("shiroFilterFactoryBean") public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, ShiroFilterChainDefinition shiroFilterChainDefinition) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); // Since there is no jwtfitter defined, comment it out here /*Map<String, Filter> filters = new HashMap<>(); filters.put("jwt", jwtFilter); shiroFilter.setFilters(filters);*/ Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap(); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; }
Note that:
SecurityManager needs to be introduced manually by ourselves or it will be red
import org.apache.shiro.mgt.SecurityManager;
After successful startup, we visited http://localhost:8081/user/index Then there will be a problem: 404 errors were successfully intercepted, but some were 500 errors. Why? This is why we need to talk about the default connection configuration of shiro-redis, which accesses 127.0.0.0:6379, or local redis. We can't access redis naturally without redis locally. How to access redis on virtual machines requires additional configuration.
The next step is to start implementing the jwtFilter filter code.
Change the filter back to jwt and remove the comment.
@Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); Map<String, String> filterMap = new LinkedHashMap<>(); filterMap.put("/**", "jwt"); // Verify permissions mainly through annotations chainDefinition.addPathDefinitions(filterMap); return chainDefinition; } @Bean("shiroFilterFactoryBean") public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager, ShiroFilterChainDefinition shiroFilterChainDefinition) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); shiroFilter.setSecurityManager(securityManager); Map<String, Filter> filters = new HashMap<>(); filters.put("jwt", jwtFilter); shiroFilter.setFilters(filters); Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap(); shiroFilter.setFilterChainDefinitionMap(filterMap); return shiroFilter; }
Automatically inject our jwtFilter
@Autowired private JwtFilter jwtFilter;
Experience
Write the whole login process tomorrow. Today, I learned shiro with a blank face. I can read a little, I can't write, I know what it is, but I don't know what its function is and what it is associated with. I guess a shiro tutorial will come out later. I think it's a challenge to understand thoroughly and tell it in more intuitive pictures or words. Whether it's a step in place or a small step in success, I hope I can finish it tomorrow, cry and look at other people's tutorials. I'm also confused. I can only search one by one to see what it is. My head is cracked, my eyes are painful, facing the computer, my eyes are bitter, don't drop my hair.
2021/11/23 0:44 more
ps: You really remember to write the time on it.