1
hao
2025-05-20 8e24c6fea30d9b179375ee2893710cdec2443b13
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
package com.config;
 
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.filter.KickoutSessionFilter;
import com.shiro.RetryLimitHashedCredentialsMatcher;
import com.shiro.ShiroRealm;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
 
import javax.servlet.Filter;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
 
/**
 * @项目名称:wyait-manage
 * @包名:com.wyait.manage.config
 * @类描述:
 * @创建人:wyait
 * @创建时间:2017-12-12 18:51
 * @version:V1.0
 */
@Configuration
@EnableTransactionManagement
public class ShiroConfig {
    private static final Logger logger = LoggerFactory
            .getLogger(ShiroConfig.class);
 
    /**
     * ShiroFilterFactoryBean 处理拦截资源文件过滤器
     * </br>1,配置shiro安全管理器接口securityManage;
     * </br>2,shiro 连接约束配置filterChainDefinitions;
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(
            org.apache.shiro.mgt.SecurityManager securityManager) {
        //shiroFilterFactoryBean对象
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        logger.debug("-----------------Shiro拦截器工厂类注入开始");
        // 配置shiro安全管理器 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //添加kickout认证
        HashMap<String, Filter> hashMap = new HashMap<String, Filter>();
        hashMap.put("kickout", kickoutSessionFilter());
        shiroFilterFactoryBean.setFilters(hashMap);
 
        // 指定要求登录时的链接
        shiroFilterFactoryBean.setLoginUrl("/toLogin");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/home");
        // 未授权时跳转的界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
 
        // filterChainDefinitions拦截器=map必须用:LinkedHashMap,因为它必须保证有序
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        // 配置退出过滤器,具体的退出代码Shiro已经实现
        filterChainDefinitionMap.put("/logout", "logout");
        //配置记住我或认证通过可以访问的地址
        filterChainDefinitionMap.put("/user/userList", "user");
        filterChainDefinitionMap.put("/", "user");
        //filterChainDefinitionMap.put("/sysPermission/*", "user");
//
//        // 配置不会被拦截的链接 从上向下顺序判断
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/css/*", "anon");
        filterChainDefinitionMap.put("/css/*/*", "anon");
        filterChainDefinitionMap.put("/js/*", "anon");
        filterChainDefinitionMap.put("/js/*/*", "anon");
        filterChainDefinitionMap.put("/js/*/*/*", "anon");
        filterChainDefinitionMap.put("/img/*", "anon");
        filterChainDefinitionMap.put("/images/*/**", "anon");
        filterChainDefinitionMap.put("/layui/*", "anon");
        filterChainDefinitionMap.put("/layui/*/**", "anon");
        filterChainDefinitionMap.put("/layuiadmin/*", "anon");
        filterChainDefinitionMap.put("/layuiadmin/*/**", "anon");
        filterChainDefinitionMap.put("/layuiadmin/*/*/**", "anon");
        filterChainDefinitionMap.put("/layuiadmin/*/*/*/**", "anon");
        filterChainDefinitionMap.put("/layuiadmin/*/*/*/*/**", "anon");
        filterChainDefinitionMap.put("/treegrid/*", "anon");
        filterChainDefinitionMap.put("/treegrid/*/*", "anon");
        filterChainDefinitionMap.put("/fragments/*", "anon");
        filterChainDefinitionMap.put("/layout", "anon");
 
        filterChainDefinitionMap.put("/generalKanBanPage/*", "anon");//通用看板
 
        filterChainDefinitionMap.put("/kanban/toDemo", "anon");//看板demo
        filterChainDefinitionMap.put("/kanban/*", "anon");//看板
        filterChainDefinitionMap.put("/kanban/*/*", "anon");//看板
        filterChainDefinitionMap.put("/kanban/*/*/*", "anon");//看板
 
 
        filterChainDefinitionMap.put("/spc/chart/*", "anon");//SPC
        filterChainDefinitionMap.put("/spc/chart/*/*", "anon");//SPC
        filterChainDefinitionMap.put("/spc/chart/*/*/*", "anon");//SPC
 
 
        filterChainDefinitionMap.put("/dev/*", "anon");//看板
        filterChainDefinitionMap.put("/template/*", "anon");//看板
 
 
        //gltAndWd_pda
        filterChainDefinitionMap.put("/user/sendMsg", "anon");
        filterChainDefinitionMap.put("/user/login", "anon");
        //filterChainDefinitionMap.put("/home", "anon");//首页
        filterChainDefinitionMap.put("/login1", "anon");
        filterChainDefinitionMap.put("/queryPurview", "anon");
        filterChainDefinitionMap.put("/getRfSetup", "anon");
        filterChainDefinitionMap.put("/getExcProc", "anon");
        filterChainDefinitionMap.put("/getCursor", "anon");
        filterChainDefinitionMap.put("/create/*", "anon");
        filterChainDefinitionMap.put("/little/*", "anon");
        filterChainDefinitionMap.put("/pinput/*", "anon");
        filterChainDefinitionMap.put("/out/*", "anon");
        filterChainDefinitionMap.put("/glue/*", "anon");
        filterChainDefinitionMap.put("/glueinput/*", "anon");
        filterChainDefinitionMap.put("/queryAppVersion", "anon");
        filterChainDefinitionMap.put("/base_file/*", "anon");//pda-ftp附件管理
        filterChainDefinitionMap.put("/getPrintInfoById", "anon");
        filterChainDefinitionMap.put("/getExcuteSql", "anon");//sql查询
 
        //lyt_pda
        filterChainDefinitionMap.put("/lyt_file/*", "anon");//ftp
        filterChainDefinitionMap.put("/lyt_file_sign/*", "anon");//ftp-样品签名附件管理
        filterChainDefinitionMap.put("/coat_item/*", "anon");//PQC-涂布项目
        filterChainDefinitionMap.put("/pqc_first_input/*", "anon");//PQC首检录入
        filterChainDefinitionMap.put("/defect_input/*", "anon");//不良投入
        filterChainDefinitionMap.put("/pqc_patrol_input/*", "anon");//PQC巡检录入
        filterChainDefinitionMap.put("/pqc_sample_input/*", "anon");//PQC抽检录入
        filterChainDefinitionMap.put("/pqc_retest_input/*", "anon");//PQC复测抽检录入
        filterChainDefinitionMap.put("/sample_sign/*", "anon");//PQC样品签字录入
        filterChainDefinitionMap.put("/pqc_pole_piece/*", "anon");//PQC极片露空时间录入
        filterChainDefinitionMap.put("/fqcPatrol/*", "anon");//FQC,OQC
        filterChainDefinitionMap.put("/equipment_inspection/*", "anon");//设备点检
        filterChainDefinitionMap.put("/SJPatrol/*", "anon");//首检
        filterChainDefinitionMap.put("/ho_patrol/*", "anon");//检验删除
 
 
        //swagger
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
 
 
        filterChainDefinitionMap.put("/io_dhs/getMesInfo", "anon");//用于德和盛设备调用接口,获取MES数据
        filterChainDefinitionMap.put("/api/uploadDeviceData", "anon");//用于德和盛设备调用接口,获取MES数据
 
        filterChainDefinitionMap.put("/api/apk/**", "anon");//apk接口
 
 
        filterChainDefinitionMap.put("/heyi/login1", "anon");
        filterChainDefinitionMap.put("/heyi/queryPurview", "anon");
        filterChainDefinitionMap.put("/heyi/getRfSetup", "anon");
        filterChainDefinitionMap.put("/heyi/getExcProc", "anon");
        filterChainDefinitionMap.put("/heyi/create/*", "anon");
        filterChainDefinitionMap.put("/heyi/little/*", "anon");
        filterChainDefinitionMap.put("/heyi/pinput/*", "anon");
        filterChainDefinitionMap.put("/heyi/out/*", "anon");
 
        filterChainDefinitionMap.put("/rk_file/*", "anon");//ftp附件录入
 
 
        filterChainDefinitionMap.put("/heyi/template/*", "anon");
        filterChainDefinitionMap.put("/heyi/dev/*", "anon");
        filterChainDefinitionMap.put("/hyKanban/*", "anon");
 
        // 海关
        filterChainDefinitionMap.put("/hgReport/*", "anon");//看板
        // 宁波亿纬
        filterChainDefinitionMap.put("/eveReport/*", "anon");//看板
        // 格林泰
        filterChainDefinitionMap.put("/gltReport/*", "anon");//
 
        // 格林泰
        filterChainDefinitionMap.put("/standard/*", "anon");
 
        filterChainDefinitionMap.put("/largeScreen/*", "anon");//看板
 
        //sop
        filterChainDefinitionMap.put("/kl_file/*", "anon");
        filterChainDefinitionMap.put("/jhsop/*", "anon");
        filterChainDefinitionMap.put("/sop/*", "anon");
 
 
        //filterChainDefinitionMap.put("/console", "anon");//首页内容
//        /*filterChainDefinitionMap.put("/page", "anon");
//        filterChainDefinitionMap.put("/channel/record", "anon");*/
        filterChainDefinitionMap.put("/user/delUser", "authc,perms[usermanage]");
//        //add操作,该用户必须有【addOperation】权限
////        filterChainDefinitionMap.put("/add", "perms[addOperation]");
//
//        // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问【放行】-->
        filterChainDefinitionMap.put("/**", "kickout,authc");
        filterChainDefinitionMap.put("/*/*", "authc");
        filterChainDefinitionMap.put("/*/*/*", "authc");
        filterChainDefinitionMap.put("/*/*/*/**", "authc");
 
        shiroFilterFactoryBean
                .setFilterChainDefinitionMap(filterChainDefinitionMap);
        logger.debug("-----------------Shiro拦截器工厂类注入成功");
        return shiroFilterFactoryBean;
    }
 
    /**
     * shiro安全管理器设置realm认证和ehcache缓存管理
     *
     * @return
     */
    @Bean
    public org.apache.shiro.mgt.SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(shiroRealm());
        // //注入ehcache缓存管理器;
        securityManager.setCacheManager(ehCacheManager());
        // //注入session管理器;
        securityManager.setSessionManager(sessionManager());
        //注入Cookie记住我管理器
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }
 
    /**
     * 身份认证realm; (账号密码校验;权限等)
     *
     * @return
     */
    @Bean
    public ShiroRealm shiroRealm() {
        ShiroRealm shiroRealm = new ShiroRealm();
        //使用自定义的CredentialsMatcher进行密码校验和输错次数限制
        shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return shiroRealm;
    }
 
    /**
     * ehcache缓存管理器;shiro整合ehcache:
     * 通过安全管理器:securityManager
     * 单例的cache防止热部署重启失败
     *
     * @return EhCacheManager
     */
    @Bean
    public EhCacheManager ehCacheManager() {
        logger.debug(
                "=====shiro整合ehcache缓存:ShiroConfiguration.getEhCacheManager()");
        EhCacheManager ehcache = new EhCacheManager();
        CacheManager cacheManager = CacheManager.getCacheManager("shiro");
        if (cacheManager == null) {
            try {
 
                cacheManager = CacheManager.create(ResourceUtils.getInputStreamForPath("classpath:config/ehcache.xml"));
 
            } catch (CacheException | IOException e) {
                e.printStackTrace();
            }
        }
        ehcache.setCacheManager(cacheManager);
        return ehcache;
    }
 
    /**
     * 设置记住我cookie过期时间
     *
     * @return
     */
    @Bean
    public SimpleCookie remeberMeCookie() {
        logger.debug("记住我,设置cookie过期时间!");
        //cookie名称;对应前端的checkbox的name = rememberMe
        SimpleCookie scookie = new SimpleCookie("rememberMe");
        //记住我cookie生效时间30天 ,单位秒  [10天]
        scookie.setMaxAge(864000);
        return scookie;
    }
 
    /**
     * 配置cookie记住我管理器
     *
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager() {
        logger.debug("配置cookie记住我管理器!");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(remeberMeCookie());
        return cookieRememberMeManager;
    }
 
    /**
     * 凭证匹配器 (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     * 所以我们需要修改下doGetAuthenticationInfo中的代码,更改密码生成规则和校验的逻辑一致即可; )
     *
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(ehCacheManager());
        //new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1);// 散列的次数,比如散列两次,相当于 // md5(md5(""));
        return hashedCredentialsMatcher;
    }
 
    /**
     * @return
     * @描述:ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
     * @创建人:wyait
     * @创建时间:2017年12月21日 下午1:52:59
     */
    @Bean
    public ShiroDialect shiroDialect() {
        return new ShiroDialect();
    }
 
    /**
     * EnterpriseCacheSessionDAO shiro sessionDao层的实现;
     * 提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。
     */
    @Bean
    public EnterpriseCacheSessionDAO enterCacheSessionDAO() {
        EnterpriseCacheSessionDAO enterCacheSessionDAO = new EnterpriseCacheSessionDAO();
        //添加缓存管理器
        //enterCacheSessionDAO.setCacheManager(ehCacheManager());
        //添加ehcache活跃缓存名称(必须和ehcache缓存名称一致)
        enterCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
        return enterCacheSessionDAO;
    }
 
    /**
     * @return
     * @描述:sessionManager添加session缓存操作DAO
     * @创建人:wyait
     * @创建时间:2018年4月24日 下午8:13:52
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //sessionManager.setCacheManager(ehCacheManager());
        sessionManager.setSessionDAO(enterCacheSessionDAO());
        sessionManager.setSessionIdCookie(sessionIdCookie());
        return sessionManager;
    }
 
    /**
     * @return
     * @描述:自定义cookie中session名称等配置
     * @创建人:wyait
     * @创建时间:2018年5月8日 下午1:26:23
     */
    @Bean
    public SimpleCookie sessionIdCookie() {
        //DefaultSecurityManager
        SimpleCookie simpleCookie = new SimpleCookie();
        //sessionManager.setCacheManager(ehCacheManager());
        //如果在Cookie中设置了"HttpOnly"属性,那么通过程序(JS脚本、Applet等)将无法读取到Cookie信息,这样能有效的防止XSS攻击。
        simpleCookie.setHttpOnly(true);
        simpleCookie.setName("SHRIOSESSIONID");
        //单位秒
        simpleCookie.setMaxAge(86400);
        return simpleCookie;
    }
 
    /**
     * @return
     * @描述:kickoutSessionFilter同一个用户多设备登录限制
     * @创建人:wyait
     * @创建时间:2018年4月24日 下午8:14:28
     */
    public KickoutSessionFilter kickoutSessionFilter() {
        KickoutSessionFilter kickoutSessionFilter = new KickoutSessionFilter();
        //使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的;
        //这里我们还是用之前shiro使用的ehcache实现的cacheManager()缓存管理
        //也可以重新另写一个,重新配置缓存时间之类的自定义缓存属性
        kickoutSessionFilter.setCacheManager(ehCacheManager());
        //用于根据会话ID,获取会话进行踢出操作的;
        kickoutSessionFilter.setSessionManager(sessionManager());
        //是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序。
        kickoutSessionFilter.setKickoutAfter(false);
        //同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录;
        kickoutSessionFilter.setMaxSession(1);
        //被踢出后重定向到的地址;
        kickoutSessionFilter.setKickoutUrl("/toLogin?kickout=1");
        return kickoutSessionFilter;
    }
 
    /**
     * @return
     * @描述:开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * </br>Enable Shiro Annotations for Spring-configured beans. Only run after the lifecycleBeanProcessor(保证实现了Shiro内部lifecycle函数的bean执行) has run
     * </br>不使用注解的话,可以注释掉这两个配置
     * @创建人:wyait
     * @创建时间:2018年5月21日 下午6:07:56
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
 
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
 
}