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 处理拦截资源文件过滤器 *
1,配置shiro安全管理器接口securityManage; *
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 hashMap = new HashMap(); hashMap.put("kickout", kickoutSessionFilter()); shiroFilterFactoryBean.setFilters(hashMap); // 指定要求登录时的链接 shiroFilterFactoryBean.setLoginUrl("/toLogin"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/home"); // 未授权时跳转的界面; shiroFilterFactoryBean.setUnauthorizedUrl("/error"); // filterChainDefinitions拦截器=map必须用:LinkedHashMap,因为它必须保证有序 Map filterChainDefinitionMap = new LinkedHashMap(); // 配置退出过滤器,具体的退出代码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]"); // // // 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)即可实现此功能 *
Enable Shiro Annotations for Spring-configured beans. Only run after the lifecycleBeanProcessor(保证实现了Shiro内部lifecycle函数的bean执行) has run *
不使用注解的话,可以注释掉这两个配置 * @创建人: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; } }