参考文档: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共享

 

posted on 2018-08-01 17:46  梓木的稻稻  阅读(967)  评论(0编辑  收藏  举报