package com.iformall.config; import com.iformall.service.MallPermissionService; import com.iformall.shiro.MyRetryLimitCredentialsMatcher; import com.iformall.shiro.MyShiroRealm; 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.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.servlet.Filter; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import java.util.LinkedHashMap; import java.util.Map; /** * Created by yangqj on 2017/4/23. */ @Configuration public class ShiroConfig { @Value("${spring.redis.host}") private String host; @Value("${spring.redis.port}") private int port; @Value("${spring.redis.timeout}") private int timeout; @Value("${spring.redis.expire}") private int expire; @Value("${spring.redis.password}") private String password; @Bean public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean * @return */ // @Bean // public ShiroDialect shiroDialect() { // return new ShiroDialect(); // } /** * ShiroFilterFactoryBean 处理拦截资源文件问题。 * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在 * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager *

* Filter Chain定义说明 * 1、一个URL可以配置多个Filter,使用逗号分隔 * 2、当设置多个过滤器时,全部验证通过,才视为通过 * 3、部分过滤器可指定参数,如perms,roles */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); Map filters = new LinkedHashMap(); filters.put("token", new ShiroLoginFilter()); filters.put("corsFilter", new RestFilter()); //filters.put("authc", new MyFormAuthenticationFilter()); shiroFilterFactoryBean.setFilters(filters); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/#/"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/usersPage"); //未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //拦截器. Map filterChainDefinitionMap = new LinkedHashMap(); //filterChainDefinitionMap.put("/ue/**", "anon"); //filterChainDefinitionMap.put("/config.json", "anon"); // login filterChainDefinitionMap.put("/doLogin/**", "anon"); filterChainDefinitionMap.put("/bHidLogin/**", "anon"); filterChainDefinitionMap.put("/sendLoginPhoneCode/**", "anon"); filterChainDefinitionMap.put("/doLoginByPhone/**", "anon"); filterChainDefinitionMap.put("/wechat/login", "anon"); // 微信第三方登录callback filterChainDefinitionMap.put("/wechat/callback", "anon"); // 微信网页登录回调 filterChainDefinitionMap.put("/wechat/weChatUserLogin", "anon"); // 微信第三方登录 // 验证码 filterChainDefinitionMap.put("/captcha.jpg", "anon"); // 官网 filterChainDefinitionMap.put("/wxMallApply/add", "anon"); // callback filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); // 支付回调 filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); filterChainDefinitionMap.put("/wxMsgCallback/**", "anon"); filterChainDefinitionMap.put("/user/sendvalidationcode", "anon"); filterChainDefinitionMap.put("/user/updatepwd", "anon"); filterChainDefinitionMap.put("/carCallback/**", "anon"); filterChainDefinitionMap.put("/wxMallApply/sendvalidationcode", "anon"); // 补发消息 filterChainDefinitionMap.put("/wxCoupon/updateStokeAndValidDate", "anon"); // static files filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/font-awesome/**", "anon"); //:这是一个坑呢,一不小心代码就不好使了; // //自定义加载权限资源关系 // Map map = new HashMap<>(); // List resourcesList = resourcesService.list(map); // for(SysPermission resources:resourcesList){ // // if (StringUtil.isNotEmpty(resources.getUrl())) { // String permission = "perms[" + resources.getUrl()+ "]"; // filterChainDefinitionMap.put(resources.getUrl(),permission); // } // } // swagger-ui filterChainDefinitionMap.put("/swagger-ui.html", "anon"); filterChainDefinitionMap.put("/doc.html", "anon"); filterChainDefinitionMap.put("/v2/**", "anon"); filterChainDefinitionMap.put("/swagger-resources/**", "anon"); filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/version", "anon"); //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "authc"); filterChainDefinitionMap.put("/**", "corsFilter,token,authc"); // filterChainDefinitionMap.put("/**", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } public static boolean isAjax(ServletRequest request) { String header = ((HttpServletRequest) request).getHeader("X-Requested-With"); if ("XMLHttpRequest".equalsIgnoreCase(header)) { System.out.println("当前请求为Ajax请求"); return Boolean.TRUE; } System.out.println("当前请求非Ajax请求"); return Boolean.FALSE; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //设置realm. securityManager.setRealm(myShiroRealm()); // 自定义缓存实现 使用redis //securityManager.setCacheManager(cacheManager()); // 自定义session管理 使用redis securityManager.setSessionManager(sessionManager()); return securityManager; } @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } /** * 密码匹配凭证管理器 凭证匹配器 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 * 所以我们需要修改下doGetAuthenticationInfo中的代码; * ) * * @return */ public MyRetryLimitCredentialsMatcher hashedCredentialsMatcher() { MyRetryLimitCredentialsMatcher hashedCredentialsMatcher = new MyRetryLimitCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); return hashedCredentialsMatcher; } /** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * 配置shiro redisManager * 使用的是shiro-redis开源插件 * * @return */ public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); redisManager.setHost(host); redisManager.setPort(port); //redisManager.setExpire(expire);// 配置缓存过期时间 redisManager.setTimeout(timeout); redisManager.setPassword(password); return redisManager; } /** * cacheManager 缓存 redis实现 * 使用的是shiro-redis开源插件 * * @return */ public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * RedisSessionDAO shiro sessionDao层的实现 通过redis * 使用的是shiro-redis开源插件 */ @Bean public RedisSessionDAO redisSessionDAO() { RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); return redisSessionDAO; } /** * shiro session的管理 */ @Bean public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); //设置session过期时间为1小时(单位:毫秒),默认为30分钟 sessionManager.setGlobalSessionTimeout(60 * 60 * 1000); sessionManager.setSessionValidationSchedulerEnabled(true); sessionManager.setSessionIdUrlRewritingEnabled(false); sessionManager.setSessionDAO(redisSessionDAO()); sessionManager.setSessionIdCookie(simpleCookie()); return sessionManager; } @Bean public SimpleCookie simpleCookie() { SimpleCookie simpleCookie = new SimpleCookie("SSIDS"); simpleCookie.setDomain(""); return simpleCookie; } // @Bean // public SimpleCookie rememberMeCookie(){ // //System.out.println("ShiroConfiguration.rememberMeCookie()"); // //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe // SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); // // // simpleCookie.setMaxAge(60*30); // return simpleCookie; // } // @Bean // public CookieRememberMeManager rememberMeManager(){ // //System.out.println("ShiroConfiguration.rememberMeManager()"); // CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); // cookieRememberMeManager.setCookie(rememberMeCookie()); // //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) // cookieRememberMeManager.setCipherKey(Base64.decodeBytes("2AvVhdsgUs0FSA3SDFAdag==")); // return cookieRememberMeManager; // } // @Bean(name = "securityManager") // public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){ // DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // //设置realm // securityManager.setRealm(realm); // //用户授权/认证信息Cache, 采用EhCache缓存 // securityManager.setCacheManager(cacheManager()); // //注入记住我管理器 // securityManager.setRememberMeManager(rememberMeManager()); // return securityManager; // } }