1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package cn.wisenergy.chnmuseum.party.conf;
import cn.wisenergy.chnmuseum.party.auth.filter.JwtFilter;
import cn.wisenergy.chnmuseum.party.auth.realm.MyShiroRealm;
import cn.wisenergy.chnmuseum.party.model.PermissionInit;
import cn.wisenergy.chnmuseum.party.service.PermissionInitService;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import redis.clients.jedis.JedisPoolConfig;
import javax.annotation.Resource;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
//@Configuration
//@Order(1)
public class ShiroConfig {
private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
private static final String CACHE_KEY = "shiro:cache:";
@Resource
private PermissionInitService permissionInitService;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxActive;
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* <p>
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* <p>
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
* <p>
* <p>
* <p>
* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过
* <p>
* 3、部分过滤器可指定参数,如perms,roles
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 未授权界面
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 自定义拦截器
Map<String, Filter> filtersMap = shiroFilterFactoryBean.getFilters();
filtersMap.put("jwt", new JwtFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// 权限控制map
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
List<PermissionInit> list = this.permissionInitService.selectAll();
for (PermissionInit permissionInit : list) {
filterChainDefinitionMap.put(permissionInit.getUrl(), permissionInit.getPermissionInit());
}
// 访问401和404页面不通过我们的Filter
filterChainDefinitionMap.put("/logout", "anon");
filterChainDefinitionMap.put("/verifyCode", "anon");
filterChainDefinitionMap.put("/ajaxLogin1", "anon");
filterChainDefinitionMap.put("/verifyCode1", "anon");
filterChainDefinitionMap.put("/404", "anon");
filterChainDefinitionMap.put("/500", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean("securityManager")
public DefaultWebSecurityManager securityManager() {
logger.info("ShiroConfiguration.securityManager()");
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm
securityManager.setRealm(myShiroRealm());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(redisCacheManager());
// 关闭shiro自带的session
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
/**
* 身份认证realm; (这个需要自己写,账号密码校验;权限等)
*/
@Bean
public MyShiroRealm myShiroRealm() {
// //开启全局缓存配置
// myShiroRealm.setCachingEnabled(true);
// //启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
// myShiroRealm.setAuthenticationCachingEnabled(true);
// //启用授权缓存,即缓存AuthorizationInfo信息,默认false
// myShiroRealm.setAuthorizationCachingEnabled(true);
//
// //为了方便操作,我们给缓存起个名字
// myShiroRealm.setAuthenticationCacheName("authcCache");
// myShiroRealm.setAuthorizationCacheName("authzCache");
//
// //注入缓存实现
// myShiroRealm.setCacheManager(redisCacheManager());
return new MyShiroRealm();
}
/**
* LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,
* 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。
* 主要是AuthorizingRealm类的子类,以及EhCacheManager类。 Shiro生命周期处理器
*/
@Bean
public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
logger.info("ShiroConfiguration.getLifecycleBeanPostProcessor()");
return new LifecycleBeanPostProcessor();
}
/**
* DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
* 实现AOP式方法级权限检查
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
logger.info("ShiroConfiguration.defaultAdvisorAutoProxyCreator()");
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
//defaultAdvisorAutoProxyCreator.setUsePrefix(true);
// 强制使用cglib,防止重复代理和可能引起代理出错的问题
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
* 开启shiro的aop注解支持. 使用代理方式; 所以需要开启代码支持;
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
logger.info("ShiroConfiguration.authorizationAttributeSourceAdvisor()");
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
/**
* 配置Redis管理器
*
* @return
* @Attention 使用的是shiro-redis开源插件
*/
@Bean
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host + ":" + port);
redisManager.setTimeout(timeout);
redisManager.setPassword(password);
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxIdle + maxActive);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
redisManager.setJedisPoolConfig(jedisPoolConfig);
return redisManager;
}
/**
* 用户授权信息Cache, 采用Redis
*/
@Bean
public RedisCacheManager redisCacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
//redisCacheManager.setKeyPrefix(CACHE_KEY);
// shiro-redis要求放在session里面的实体类必须有个id标识
//这是组成redis中所存储数据的key的一部分
redisCacheManager.setPrincipalIdFieldName("id");
//用户权限信息缓存时间
//redisCacheManager.setExpire(200000);
return redisCacheManager;
}
}