package com.gkhy.assess.framework.shiro;
|
|
import com.gkhy.assess.framework.shiro.filter.JwtFilter;
|
import com.gkhy.assess.framework.shiro.realm.UserRealm;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
|
import org.apache.shiro.mgt.DefaultSubjectDAO;
|
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
|
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
|
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.crazycake.shiro.IRedisManager;
|
import org.crazycake.shiro.RedisCacheManager;
|
import org.crazycake.shiro.RedisClusterManager;
|
import org.crazycake.shiro.RedisManager;
|
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.DependsOn;
|
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
import redis.clients.jedis.HostAndPort;
|
import redis.clients.jedis.JedisCluster;
|
|
import javax.annotation.Resource;
|
import javax.servlet.Filter;
|
import java.util.HashSet;
|
import java.util.Set;
|
|
@Configuration
|
@Slf4j
|
public class ShiroConfig {
|
|
@Resource
|
private LettuceConnectionFactory lettuceConnectionFactory;
|
|
@Bean
|
public JwtFilter jwtFilter() {
|
//过滤器如果加了@Compoent就没必要用这个方法了
|
return new JwtFilter();
|
}
|
|
@Bean
|
public FilterRegistrationBean<Filter> registration(JwtFilter filter) {
|
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<Filter>(new JwtFilter());
|
registration.setEnabled(true);
|
return registration;
|
}
|
|
|
@Bean
|
public ShiroFilterChainDefinition shiroFilterChainDefinition(){
|
DefaultShiroFilterChainDefinition chain=new DefaultShiroFilterChainDefinition();
|
|
//放行Swagger2页面
|
chain.addPathDefinition("/swagger-ui.html","anon");
|
chain.addPathDefinition("/swagger/**","anon");
|
chain.addPathDefinition("/webjars/**", "anon");
|
chain.addPathDefinition("/swagger-resources/**","anon");
|
|
chain.addPathDefinition("/account/login","anon");
|
// chain.addPathDefinition("/api/account/login","anon");
|
chain.addPathDefinition("/logout", "logout");
|
|
chain.addPathDefinition("/system/notice/noticeList","anon");
|
chain.addPathDefinition("/system/notice/getNoticeById","anon");
|
|
chain.addPathDefinition("/system/law/lawList","anon");
|
chain.addPathDefinition("/system/law/getLawById","anon");
|
|
chain.addPathDefinition("/system/agency/agencyList","anon");
|
chain.addPathDefinition("/system/agency/getAgencyById","anon");
|
|
chain.addPathDefinition("/system/user/agencyRegister","anon");
|
chain.addPathDefinition("/system/captcha/captchaImage","anon");
|
|
//除了以上的请求外,其它请求都需要登录
|
chain.addPathDefinition("/**", "jwtFilter,authc"); // 需登录才能访问
|
|
// chain.addPathDefinition("/**", "anon"); // 需登录才能访问
|
return chain;
|
|
}
|
|
|
@Bean
|
public DefaultWebSecurityManager securityManager(UserRealm realm){
|
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
|
securityManager.setRealm(realm);
|
// 关闭shiro自带的session
|
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
|
//禁用session, 不保存用户登录状态。保证每次请求都重新认证
|
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator=new DefaultSessionStorageEvaluator();
|
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
|
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
|
securityManager.setSubjectDAO(subjectDAO);
|
//自定义缓存实现,使用redis
|
securityManager.setCacheManager(redisCacheManager());
|
|
return securityManager;
|
}
|
|
/**
|
* 下面的代码是添加注解支持
|
* @return
|
*/
|
@Bean
|
@DependsOn("lifecycleBeanPostProcessor")
|
public static DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
|
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
|
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
|
/**
|
* setUsePrefix(false)用于解决一个奇怪的bug。在引入spring aop的情况下。
|
* 在@Controller注解的类的方法中加入@RequiresRole注解,会导致该方法无法映射请求,导致返回404。
|
* 加入这项配置能解决这个bug
|
*/
|
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
|
defaultAdvisorAutoProxyCreator.setAdvisorBeanNamePrefix("_no_advisor");
|
return defaultAdvisorAutoProxyCreator;
|
}
|
|
@Bean
|
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
|
return new LifecycleBeanPostProcessor();
|
}
|
|
|
@Bean
|
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
|
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
|
advisor.setSecurityManager(securityManager);
|
return advisor;
|
}
|
|
/**
|
* cacheManager 缓存 redis实现
|
* 使用的是shiro-redis开源插件
|
*
|
* @return
|
*/
|
public RedisCacheManager redisCacheManager() {
|
log.info("===============(1)创建缓存管理器RedisCacheManager");
|
RedisCacheManager redisCacheManager = new RedisCacheManager();
|
redisCacheManager.setRedisManager(redisManager());
|
//redis中针对不同用户缓存(此处的id需要对应user实体中的id字段,用于唯一标识)
|
redisCacheManager.setPrincipalIdFieldName("id");
|
//用户权限信息缓存时间
|
redisCacheManager.setExpire(200000);
|
return redisCacheManager;
|
}
|
|
|
/**
|
* 来源jeecg-boot项目
|
* 配置shiro redisManager
|
* 使用的是shiro-redis开源插件
|
*
|
* @return
|
*/
|
@Bean
|
public IRedisManager redisManager() {
|
log.info("===============(2)创建RedisManager,连接Redis..");
|
IRedisManager manager;
|
// redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
|
if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
|
RedisManager redisManager = new RedisManager();
|
redisManager.setHost(lettuceConnectionFactory.getHostName() + ":" + lettuceConnectionFactory.getPort());
|
//(lettuceConnectionFactory.getPort());
|
redisManager.setDatabase(lettuceConnectionFactory.getDatabase());
|
redisManager.setTimeout(0);
|
if (!StringUtils.isEmpty(lettuceConnectionFactory.getPassword())) {
|
redisManager.setPassword(lettuceConnectionFactory.getPassword());
|
}
|
manager = redisManager;
|
}else{
|
// redis集群支持,优先使用集群配置
|
RedisClusterManager redisManager = new RedisClusterManager();
|
Set<HostAndPort> portSet = new HashSet<>();
|
lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().forEach(node -> portSet.add(new HostAndPort(node.getHost() , node.getPort())));
|
//update-begin--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
|
if (StringUtils.isNotEmpty(lettuceConnectionFactory.getPassword())) {
|
JedisCluster jedisCluster = new JedisCluster(portSet, 2000, 2000, 5,
|
lettuceConnectionFactory.getPassword(), new GenericObjectPoolConfig());
|
redisManager.setPassword(lettuceConnectionFactory.getPassword());
|
redisManager.setJedisCluster(jedisCluster);
|
} else {
|
JedisCluster jedisCluster = new JedisCluster(portSet);
|
redisManager.setJedisCluster(jedisCluster);
|
}
|
//update-end--Author:scott Date:20210531 for:修改集群模式下未设置redis密码的bug issues/I3QNIC
|
manager = redisManager;
|
}
|
return manager;
|
}
|
|
|
}
|