博客代码下载
SpringBoot快速整合ShiroRedis与Thymeleaf(完整版)免费下载-Java文档类资源-CSDN下载
pom.xml
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
代码实现
一.重写ShiroWebAutoConfiguration类
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BootShiroRedisAutoConfiguration extends ShiroWebAutoConfiguration {
@Autowired
RedisSessionDAO redisSessionDAO;
@Autowired
RedisCacheManager redisCacheManager;
@Bean("shiroFilterChainDefinition")
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/api/doLogin", "anon");//你不需要拦截路径
chainDefinition.addPathDefinition("/**", "authc");//你需要拦截的路径
return chainDefinition;
}
@Bean("authorizer")//自定义SampleRealm,必须配置
public SampleRealm sampleRealm() {
return new SampleRealm();
}
//重写 SessionManager 方法
@Override
protected SessionManager sessionManager() {
if (useNativeSessionManager) {
DefaultWebSessionManager nativeSessionManager = (DefaultWebSessionManager) nativeSessionManager();
nativeSessionManager.setSessionDAO(redisSessionDAO);
return nativeSessionManager;
}
return new ServletContainerSessionManager();
}
//重写 SessionsSecurityManager 方法
protected SessionsSecurityManager securityManager(SampleRealm realms) {
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) createSecurityManager();
securityManager.setRealm(realms);
securityManager.setSessionManager(sessionManager());
securityManager.setCacheManager(redisCacheManager);
return securityManager;
}
}
二、自定义Realm,SampleRealm.java
import java.util.HashSet;
import java.util.Set;
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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import cn.itgsvip.pojo.UserVo;
public class SampleRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
UserVo principal = (UserVo) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
if ("admin".equals(principal.getUserName())) {
authorizationInfo.addRole("admin");
Set<String> permissions = new HashSet<String>();
permissions.add("admin:del");//权限
permissions.add("admin:find");
authorizationInfo.addStringPermissions(permissions);
}
if ("user".equals(principal.getUserName())) {
authorizationInfo.addRole("user");
Set<String> permissions = new HashSet<String>();
permissions.add("user:del");
permissions.add("user:find");
authorizationInfo.addStringPermissions(permissions);
}
if ("adminAndUser".equals(principal.getUserName())) {
Set<String> roles = new HashSet<String>();
roles.add("admin");//管理员角色
roles.add("user");//用户角色
authorizationInfo.addRoles(roles);
Set<String> permissions = new HashSet<String>();
permissions.add("admin:del");//权限
permissions.add("admin:find");
permissions.add("user:del");
permissions.add("user:find");
authorizationInfo.addStringPermissions(permissions);
}
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken)
throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String userName = token.getUsername();
String password = String.valueOf(token.getPassword());
UserVo user = new UserVo();
if ("admin".equals(userName)) {
user.setUserId("10001");
user.setUserName(userName);
user.setPassWord(password);
}
if ("user".equals(userName)) {
user.setUserId("10002");
user.setUserName(userName);
user.setPassWord(password);
}
if ("adminAndUser".equals(userName)) {
user.setUserId("10000");
user.setUserName(userName);
user.setPassWord(password);
}
return new SimpleAuthenticationInfo(user, password, getName());
}
}
三、application.properties配置
(1)shiro配置
官方文档地址 Apache Shiro | Simple. Java. Security.
#---------shiro配置--------------------------------------
#登录页面
shiro.loginUrl=/login
#无权限访问
shiro.unauthorizedUrl=/error
#将回话sessions交给shiro管理
shiro.userNativeSessionManager=true
#禁用URL会话重写
shiro.sessionManager.sessionIdUrlRewritingEnabled=false
#自定义cookie名字,默认JSESSIONID
shiro.sessionManager.cookie.name=Authorization
#---------shiro配置--------------------------------------
(2)shiro-redis配置
#--------------------shiro-redis配置------------------------
#redis地址
shiro-redis.redis-manager.host=127.0.0.1:6379
#redis密码
#shiro-redis.redis-manager.password=12345
#用户信息存入redis第几个库
shiro-redis.redis-manager.database=5
#实体类id,默认是id,找不到id则会报错
shiro-redis.cache-manager.principal-id-field-name=userId
#自定义redis关键字前缀的会话管理,默认shiro:session:
shiro-redis.session-dao.key-prefix=token:user-session:
#自定义redis关键字前缀缓存管理,默认shiro:cache:
shiro-redis.cache-manager.key-prefix=token:authorization:
#--------------------shiro-redis配置------------------------
(3)Thymeleaf,不需要配置,使用默认的配置既可
是的,已经集成完毕
题外话:为什么这样实现?
在你不理解为什么这样搭建的时候,下面是代码的分析步骤
1( 因为我前面发布的四篇博客都是和shiro有关的,其实都是存在问题的!比如使用 shiro-redis-spring-boot-starter 的时候,导致shiro官方提供的配置失效,_①_ 这是因为 shiro-redis-spring-boot-starter 重写了shiro官方提供的SessionManager和SecurityManager方法,没有把shiro的配置配置进去,才会导致shiro配置无效,这才是病因。
2( 我重新看了 shiro-redis-spring-boot-starter 和 shiro-spring-boot-web-starter 的源码实现,我一步一步来到了shiro-spring-boot-web-starter 实现SessionManager和SecurityManager的源码
3( 刚好shiro-redis官网有个说明,意思是,如果你不想创建shiro配置,shiro-redis-spring-boot-starter 帮忙我们创建配置,帮忙我们创建配置的时候把shiro提供的配置全部干掉了,所以又回到了 _①_ 这个问题 。
4( 既然知道问题所在了,我就动手把他们重新调整一下,就是重写了ShiroWebAutoConfiguration的SessionManager和SecurityManager方法,重写了但是并没有完全重写,只是把shiro-redis-spring-boot-starter 的配置添加进去,这样在不破坏Shiro和Shiro-Redis的配置下,然后就成功的解决了。