You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
6.3 KiB

package com.stone.conf.shiro;
import com.stone.conf.filter.AjaxPermissionsAuthorizationFilter;
import com.stone.conf.session.ShiroSessionListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
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.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* shiro 配置核心类
*
* @author zhoujl
* @since 2018-07-05
*/
@Slf4j
@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;
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*/
private RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
final String CACHE_KEY = "shiro:cache:";
redisCacheManager.setKeyPrefix(CACHE_KEY);
// 配置缓存的话要求放在session里面的实体类必须有个id标识
redisCacheManager.setPrincipalIdFieldName("id");
return redisCacheManager;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*/
private RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host + ":" + port);
redisManager.setTimeout(timeout);
return redisManager;
}
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
redisSessionDAO.setSessionIdGenerator(sessionIdGenerator());
String SESSION_KEY = "shiro:session:";
redisSessionDAO.setKeyPrefix(SESSION_KEY);
int EXPIRE = 1800;
redisSessionDAO.setExpire(EXPIRE);
return redisSessionDAO;
}
/**
* SessionID生成器
*/
@Bean
public ShiroSessionIdGenerator sessionIdGenerator(){
return new ShiroSessionIdGenerator();
}
/**
* 配置保存sessionId的cookie
*/
@Bean("sessionIdCookie")
public SimpleCookie sessionIdCookie(){
//这个参数是cookie的名称
SimpleCookie simpleCookie = new SimpleCookie("sid");
//setcookie的httponly属性如果设为true的话,会增加对xss防护的安全系数
simpleCookie.setHttpOnly(true);
simpleCookie.setPath("/");
//maxAge=-1表示浏览器关闭时失效此Cookie
simpleCookie.setMaxAge(-1);
return simpleCookie;
}
/**
* 配置session监听
*/
@Bean("sessionListener")
public ShiroSessionListener sessionListener(){
return new ShiroSessionListener();
}
/**
* Session Manager
* 使用的是shiro-redis开源插件
*/
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
Collection<SessionListener> listeners = new ArrayList<>();
// 配置监听
listeners.add(sessionListener());
webSessionManager.setSessionListeners(listeners);
webSessionManager.setSessionIdCookie(sessionIdCookie());
webSessionManager.setSessionDAO(redisSessionDAO());
// 全局会话超时时间(单位毫秒)
webSessionManager.setGlobalSessionTimeout(30 * 60 * 1000);
// 是否开启删除无效的session对象 默认为true
webSessionManager.setDeleteInvalidSessions(true);
// 是否开启定时调度器进行检测过期session 默认为true
webSessionManager.setSessionValidationSchedulerEnabled(true);
// 设置session失效的扫描时间, 清理用户直接关闭浏览器造成的孤立会话 默认为 1个小时
webSessionManager.setSessionValidationInterval(60 * 1000);
// 取消url 后面的 JSESSIONID
webSessionManager.setSessionIdUrlRewritingEnabled(false);
return webSessionManager;
}
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 配置不会被拦截的链接 顺序判断
// <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// 配置swagger访问路径 加载顺序不可改变
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/user/login", "anon");
filterChainDefinitionMap.put("/**", "user");
// 自定义拦截器
Map<String, Filter> filtersMap = new LinkedHashMap<>();
filtersMap.put("user", new AjaxPermissionsAuthorizationFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 注入 securityManager
*/
@Bean(name = "securityManager")
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() {
return new MyShiroRealm();
}
}