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;
// }
}