参考文档:https://blog.csdn.net/lishehe/article/details/45224591
1.新建表:
CREATE TABLE `admin_session` (
`session_id` text,
`session` text
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
2.重写EnterpriseCacheSessionDAO类,或者重写AbstractSessionDAO类
这是shiro session操作的核心
(1)MysqlSessionDao
package com.inslink.roboqa.shiro; /** * @author lixf * redis实现共享session */ import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.inslink.roboqa.mapper.AdminSessionMapper; import com.inslink.roboqa.model.AdminSession; import com.inslink.roboqa.util.SerializeUtils; public class MysqlSessionDao extends EnterpriseCacheSessionDAO { private static Logger logger = LoggerFactory.getLogger(MysqlSessionDao.class); @Autowired private AdminSessionMapper adminSessionMapper; @Override public void update(Session session) { logger.info("更新seesion"+session.getId()); adminSessionMapper.set(session.getId().toString(), SerializeUtils.serialize(session)); } /** * 删除session */ @Override public void delete(Session session) { logger.info("删除seesion"+session.getId()); if (session == null || session.getId() == null) { return; } adminSessionMapper.delete(session.getId().toString()); } /** * 获取存活的sessions */ @Override public Collection<Session> getActiveSessions() { Set<Session> sessions = new HashSet<>(); AdminSession adminSession = new AdminSession(); List<AdminSession> adminsessions = adminSession.selectAll(); for (AdminSession adminsession : adminsessions) { String sessionStr = adminsession.getSession(); if(StringUtils.isBlank(sessionStr)){ return null; } Session session = (Session) SerializeUtils.deserialize(sessionStr); sessions.add(session); } return sessions; } /** * 创建session */ @Override protected Serializable doCreate(Session session) { logger.info("创建seesion"+session.getId()); Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); adminSessionMapper.create(sessionId.toString(), SerializeUtils.serialize(session)); return sessionId; } /** * 获取session */ @Override protected Session doReadSession(Serializable sessionId) { logger.info("读取seesion"+sessionId); String sessionStr = adminSessionMapper.get(sessionId.toString()); if(StringUtils.isBlank(sessionStr)){ return null; } Session session = (Session) SerializeUtils.deserialize(sessionStr); return session; } }
(2)AdminSessionMapper
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.inslink.roboqa.mapper.AdminSessionMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.inslink.roboqa.model.AdminSession"> <id column="SESSION_ID" property="sessionId"/> <result column="SESSION" property="session"/> </resultMap> <update id="create"> INSERT INTO admin_session (session_id,session) VALUES(#{session_id},#{session}) </update> <update id="set"> UPDATE admin_session SET session=#{session} WHERE session_id = #{session_id} </update> <update id="delete"> DELETE FROM admin_session WHERE session_id = #{session_id} </update> <select id="get" resultType="java.lang.String"> SELECT session FROM admin_session WHERE session_id = #{session_id} </select> </mapper>
3.注册dao
package com.inslink.roboqa.shiro; 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.CookieRememberMeManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.ShiroHttpSession; 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.beans.factory.annotation.Qualifier; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.DelegatingFilterProxy; import com.alibaba.fastjson.JSON; import javax.servlet.DispatcherType; import java.util.LinkedHashMap; @Configuration public class ShiroConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class); @Bean public MysqlSessionDao mysqlSessionDao(){ return new MysqlSessionDao(); } @Bean public MysqlCacheManager mysqlCacheManager(){ return new MysqlCacheManager(); } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter")); filterRegistration.setEnabled(true); filterRegistration.addUrlPatterns("/*"); filterRegistration.setDispatcherTypes(DispatcherType.REQUEST); return filterRegistration; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(manager); //配置登录的url和登录成功的url bean.setLoginUrl("/login"); // 登录成功后要跳转的链接 bean.setSuccessUrl("/index"); // 未授权界面; bean.setUnauthorizedUrl("/403"); //配置访问权限 // Map<String, Filter>filters = new HashMap<String, Filter>(); // filters.put("perms", urlPermissionsFilter()); // filters.put("anon", new AnonymousFilter()); // bean.setFilters(filters); LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); // filterChainDefinitionMap.put("/static/**", "anon"); //表示可以匿名访问 // filterChainDefinitionMap.put("/loginUser", "anon"); // filterChainDefinitionMap.put("/login","anon"); // filterChainDefinitionMap.put("/loginIndex","authc"); // filterChainDefinitionMap.put("/static/index.html","authc"); // filterChainDefinitionMap.put("/**", "authc,perms");//表示需要认证才可以访问 // filterChainDefinitionMap.put("/*.*", "authc"); // filterChainDefinitionMap.put("/static/error.html*","anon"); // filterChainDefinitionMap.put("/*", "authc,perms");//表示需要认证才可以访问 filterChainDefinitionMap.put("/*", "anon"); filterChainDefinitionMap.put("/**", "anon"); filterChainDefinitionMap.put("/*.*", "anon"); bean.setFilterChainDefinitionMap(filterChainDefinitionMap); return bean; } @Bean public URLPermissionsFilter urlPermissionsFilter() { return new URLPermissionsFilter(); } //设置客户信息cookie管理器 @Bean(name = "rememberMeManager") public CookieRememberMeManager rememberMeManager() { CookieRememberMeManager rememberMeManager = new CookieRememberMeManager(); SimpleCookie cookie = new SimpleCookie(CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME); cookie.setHttpOnly(true); cookie.setMaxAge(24*60*60*7); return rememberMeManager; } //配置核心安全事务管理器 @Bean(name = "securityManager") public SecurityManager securityManager(@Qualifier("authRealm") AuthRealm authRealm, @Qualifier("sessionManager") DefaultWebSessionManager sessionManager, @Qualifier("rememberMeManager") CookieRememberMeManager rememberMeManager) { System.err.println("--------------shiro已经加载----------------"); DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(authRealm); manager.setRememberMeManager(rememberMeManager); manager.setSessionManager(sessionManager); //manager.setCacheManager(mysqlCacheManager()); return manager; } //设置session管理器 @Bean(name = "sessionManager") public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); SimpleCookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME); cookie.setHttpOnly(true); cookie.setMaxAge(24*60*60); sessionManager.setSessionIdCookie(cookie); sessionManager.setDeleteInvalidSessions(true);//设置是否删除无效session //sessionManager.setGlobalSessionTimeout(mysqlSessionDao().getExpireTime());//设置全局session超时时长 //mysqlSessionDao().setCacheManager(mysqlCacheManager()); sessionManager.setSessionDAO(mysqlSessionDao());//设置自定义session操作 //sessionManager.setSessionValidationSchedulerEnabled(true);//设置是否定期检查session return sessionManager; } //重写报错 @Bean(name = "exceptionResolver") public MyExceptionResolver myExceptionResolver() { return new MyExceptionResolver(); } //配置自定义的权限登录器 @Bean(name = "authRealm") public AuthRealm authRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) { AuthRealm authRealm = new AuthRealm(); authRealm.setCredentialsMatcher(matcher); return authRealm; } //配置自定义的密码比较器 @Bean(name = "credentialsMatcher") public CredentialsMatcher credentialsMatcher() { return new CredentialsMatcher(); } @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager") SecurityManager manager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(manager); return advisor; } }
ok,这样就完成了shiro+mysql的分布式session共享