自定义shiro中RedisSessionDAO的keyPrefix
  TEZNKK3IfmPf 2023年11月15日 21 0

shiro中原始的RedisSessionDAO如下,keyPrefix为shiro_redis_session:,某些情况下需要自定义这个值

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.crazycake.shiro;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RedisSessionDAO extends AbstractSessionDAO {
    private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);
    private RedisManager redisManager;
    private String keyPrefix = "shiro_redis_session:";

    public RedisSessionDAO() {
    }

    public void update(Session session) throws UnknownSessionException {
        this.saveSession(session);
    }

    private void saveSession(Session session) throws UnknownSessionException {
        if (session != null && session.getId() != null) {
            byte[] key = this.getByteKey(session.getId());
            byte[] value = SerializeUtils.serialize(session);
            session.setTimeout((long)(this.redisManager.getExpire() * 1000));
            this.redisManager.set(key, value, this.redisManager.getExpire());
        } else {
            logger.error("session or session id is null");
        }
    }

    public void delete(Session session) {
        if (session != null && session.getId() != null) {
            this.redisManager.del(this.getByteKey(session.getId()));
        } else {
            logger.error("session or session id is null");
        }
    }

    public Collection<Session> getActiveSessions() {
        Set<Session> sessions = new HashSet();
        Set<byte[]> keys = this.redisManager.keys(this.keyPrefix + "*");
        if (keys != null && keys.size() > 0) {
            Iterator i$ = keys.iterator();

            while(i$.hasNext()) {
                byte[] key = (byte[])i$.next();
                Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
                sessions.add(s);
            }
        }

        return sessions;
    }

    protected Serializable doCreate(Session session) {
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
        return sessionId;
    }

    protected Session doReadSession(Serializable sessionId) {
        if (sessionId == null) {
            logger.error("session id is null");
            return null;
        } else {
            Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
            return s;
        }
    }

    private byte[] getByteKey(Serializable sessionId) {
        String preKey = this.keyPrefix + sessionId;
        return preKey.getBytes();
    }

    public RedisManager getRedisManager() {
        return this.redisManager;
    }

    public void setRedisManager(RedisManager redisManager) {
        this.redisManager = redisManager;
        this.redisManager.init();
    }

    public String getKeyPrefix() {
        return this.keyPrefix;
    }

    public void setKeyPrefix(String keyPrefix) {
        this.keyPrefix = keyPrefix;
    }
}

自定义:

public class MyRedisSessionDAO extends RedisSessionDAO {


        private Logger logger = LoggerFactory.getLogger(MyRedisSessionDAO.class);
        private RedisManager redisManager;
        //自定义key前缀
        private String keyPrefix = "cmp_shiro_redis_session:";

        public MyRedisSessionDAO() {
        }

        public void update(Session session) throws UnknownSessionException {
            this.saveSession(session);
        }

        private void saveSession(Session session) throws UnknownSessionException {
            if (session != null && session.getId() != null) {
                byte[] key = this.getByteKey(session.getId());
                byte[] value = SerializeUtils.serialize(session);
                session.setTimeout((long)(this.redisManager.getExpire() * 1000));
                this.redisManager.set(key, value, this.redisManager.getExpire());
            } else {
                logger.error("session or session id is null");
            }
        }

        public void delete(Session session) {
            if (session != null && session.getId() != null) {
                this.redisManager.del(this.getByteKey(session.getId()));
            } else {
                logger.error("session or session id is null");
            }
        }

        public Collection<Session> getActiveSessions() {
            Set<Session> sessions = new HashSet();
            Set<byte[]> keys = this.redisManager.keys(this.keyPrefix + "*");
            if (keys != null && keys.size() > 0) {
                Iterator i$ = keys.iterator();

                while(i$.hasNext()) {
                    byte[] key = (byte[])i$.next();
                    Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
                    sessions.add(s);
                }
            }

            return sessions;
        }

        protected Serializable doCreate(Session session) {
            Serializable sessionId = this.generateSessionId(session);
            this.assignSessionId(session, sessionId);
            this.saveSession(session);
            return sessionId;
        }

        protected Session doReadSession(Serializable sessionId) {
            if (sessionId == null) {
                logger.error("session id is null");
                return null;
            } else {
                Session s = (Session) SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
                return s;
            }
        }

        private byte[] getByteKey(Serializable sessionId) {
            String preKey = this.keyPrefix + sessionId;
            return preKey.getBytes();
        }

        public RedisManager getRedisManager() {
            return this.redisManager;
        }

        public void setRedisManager(RedisManager redisManager) {
            this.redisManager = redisManager;
            this.redisManager.init();
        }

        public String getKeyPrefix() {
            return this.keyPrefix;
        }

        public void setKeyPrefix(String keyPrefix) {
            this.keyPrefix = keyPrefix;
        }


    }

然后在DefaultWebSessionManager中

/**
     * Session Manager
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }

redisSessionDAO()的实现

@Bean
    public MyRedisSessionDAO redisSessionDAO() {
        MyRedisSessionDAO redisSessionDAO = new MyRedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }

附上完整的ShiroConfig代码

package cn.com.suntree.cmp.config;

import cn.com.suntree.cmp.entity.Power;
import cn.com.suntree.cmp.entity.Role;
import cn.com.suntree.cmp.entity.SysUser;
import cn.com.suntree.cmp.service.CmpUserService;
import cn.com.suntree.cmp.utils.CommonUtil;
import cn.com.suntree.cmp.utils.YAMLUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
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.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import javax.servlet.Filter;
import java.io.Serializable;
import java.util.*;

@Log4j2
@Configuration
public class ShiroConfig {

    /**
     * @Autowired
     * @Lazy private SysUserService userService;
     */
    @Autowired
    YAMLUtils yaml;

    /**
     * @param securityManager
     * @return 拦截工厂配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //自定义拦截器
        Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
        //限制同一帐号同时在线的个数。
        filtersMap.put("kickout", kickoutSessionControlFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);
        //权限控制map
        HashMap<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/api/enclosure/download", "anon");
        filterMap.put("/api/register/**", "anon");
   
        filterMap.put("/api/enclosure/onlinePreview", "anon");
        filterMap.put("/api/**", "authc");
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setUnauthorizedUrl("/error");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    /**
     * @return 安全管理器
     */
    @Bean
    public SecurityManager securityManager(@Qualifier("myShiroRealm") MyShiroRealm myShiroRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(myShiroRealm);
        // 自定义缓存实现 使用redis
        securityManager.setCacheManager(cacheManager());
        // 自定义session管理 使用redis
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    /**
     * 身份认证realm; (这个需要自己写,账号密码校验;权限等)
     *
     * @return
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(credentialsMatcher());
        myShiroRealm.setCacheManager(cacheManager());//設置緩存
        return myShiroRealm;
    }

    /**
     * cacheManager 缓存 redis实现
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisCacheManager cacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }

    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * @return
     */
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(yaml.redis_host);
        redisManager.setPort(yaml.redis_port);
        redisManager.setExpire(yaml.redis_cache);// 配置缓存过期时间
        redisManager.setTimeout(0);
        redisManager.setPassword(yaml.redis_passwd);
        return redisManager;
    }

    /**
     * Session Manager
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO());
        return sessionManager;
    }


  
    public class MyRedisSessionDAO extends RedisSessionDAO {


        private Logger logger = LoggerFactory.getLogger(MyRedisSessionDAO.class);
        private RedisManager redisManager;
        private String keyPrefix = "cmp_shiro_redis_session:";

        public MyRedisSessionDAO() {
        }

        public void update(Session session) throws UnknownSessionException {
            this.saveSession(session);
        }

        private void saveSession(Session session) throws UnknownSessionException {
            if (session != null && session.getId() != null) {
                byte[] key = this.getByteKey(session.getId());
                byte[] value = SerializeUtils.serialize(session);
                session.setTimeout((long)(this.redisManager.getExpire() * 1000));
                this.redisManager.set(key, value, this.redisManager.getExpire());
            } else {
                logger.error("session or session id is null");
            }
        }

        public void delete(Session session) {
            if (session != null && session.getId() != null) {
                this.redisManager.del(this.getByteKey(session.getId()));
            } else {
                logger.error("session or session id is null");
            }
        }

        public Collection<Session> getActiveSessions() {
            Set<Session> sessions = new HashSet();
            Set<byte[]> keys = this.redisManager.keys(this.keyPrefix + "*");
            if (keys != null && keys.size() > 0) {
                Iterator i$ = keys.iterator();

                while(i$.hasNext()) {
                    byte[] key = (byte[])i$.next();
                    Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
                    sessions.add(s);
                }
            }

            return sessions;
        }

        protected Serializable doCreate(Session session) {
            Serializable sessionId = this.generateSessionId(session);
            this.assignSessionId(session, sessionId);
            this.saveSession(session);
            return sessionId;
        }

        protected Session doReadSession(Serializable sessionId) {
            if (sessionId == null) {
                logger.error("session id is null");
                return null;
            } else {
                Session s = (Session) SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
                return s;
            }
        }

        private byte[] getByteKey(Serializable sessionId) {
            String preKey = this.keyPrefix + sessionId;
            return preKey.getBytes();
        }

        public RedisManager getRedisManager() {
            return this.redisManager;
        }

        public void setRedisManager(RedisManager redisManager) {
            this.redisManager = redisManager;
            this.redisManager.init();
        }

        public String getKeyPrefix() {
            return this.keyPrefix;
        }

        public void setKeyPrefix(String keyPrefix) {
            this.keyPrefix = keyPrefix;
        }


    }

    /**
     * RedisSessionDAO shiro sessionDao层的实现 通过redis
     * 使用的是shiro-redis开源插件
     */
    @Bean
    public MyRedisSessionDAO redisSessionDAO() {
        MyRedisSessionDAO redisSessionDAO = new MyRedisSessionDAO();
        //自定义sessionId生成器
        //redisSessionDAO.setSessionIdGenerator(mySessionIdGenerstor());
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
/*
    @Bean
    public MySessionIdGenerstor mySessionIdGenerstor(){
        return new MySessionIdGenerstor();
    }
*/

    /**
     * 限制同一账号登录同时登录人数控制
     *
     * @return
     */
    @Bean
    public KickoutSessionControlFilter kickoutSessionControlFilter() {

        KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
        //使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的;
        //这里我们还是用之前shiro使用的redisManager()实现的cacheManager()缓存管理
        //也可以重新另写一个,重新配置缓存时间之类的自定义缓存属性
        kickoutSessionControlFilter.setCacheManager(cacheManager());
        //用于根据会话ID,获取会话进行踢出操作的;
        kickoutSessionControlFilter.setSessionManager(sessionManager());
        //是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;踢出顺序。
        kickoutSessionControlFilter.setKickoutAfter(false);
        //同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录;
        kickoutSessionControlFilter.setMaxSession(1);
        //被踢出后重定向到的地址;
        kickoutSessionControlFilter.setKickoutUrl("/kickout");
        return kickoutSessionControlFilter;
    }

    /***
     * 授权所用配置
     *
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    /**
     * @param securityManager
     * @return 授权注解支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * Shiro生命周期处理器

     @Bean public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
     return new LifecycleBeanPostProcessor();
     }
     */
    /**
     * @return 密码匹配器
     */
    @Bean
    public CredentialsMatcher credentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        return hashedCredentialsMatcher;
    }


    /**
     * 自定义 - 数据域
     */
    public class MyShiroRealm extends AuthorizingRealm {

        @Autowired
        @Lazy
        private CmpUserService userService;

        //@Autowired
        //private void setSysUserService(CmpUserService userService) {
        //this.userService = userService;
        //  }

        /**
         * @param principalCollection
         * @return
         * @implNote 功能授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SysUser user = (SysUser) principalCollection.getPrimaryPrincipal();
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

            //user = userService.getUserInfoByUserId(user.getUserID());
            user = userService.getUserDetailInfoByUserId(user.getUserID(), user.getCompanyId());
            List<Role> roleList = user.getRoleList();
            for (Role role : roleList) {
                authorizationInfo.addRole(role.getRoleName());
                if (CommonUtil.check(role.getPowerList())) {
                    for (Power permission : role.getPowerList()) {
                        authorizationInfo.addStringPermission(permission.getUrl());
                    }
                }
            }
            return authorizationInfo;
        }

        /**
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         * @implNote 身份认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            String key = (String) authenticationToken.getPrincipal();
            SysUser u = new SysUser();
            u.setAccNum(key);

            SysUser user = userService.getUserByAcc(u);
            if (user == null) {
                throw new UnknownAccountException();
            } else if ("0".equals(user.getIsLock())) {
                throw new LockedAccountException(); // 帐号冻结,非正常
                //    }
                //  SysUser admin = userService.getByUId(user.getCreaterId());
                //    if(admin != null && !"00".equals(admin.getUserState())){
                //      throw new LockedAccountException(); // 管理员帐号被冻结,非正常
            } else {
                SimpleAuthenticationInfo simpleAuthenticationInfo =
                        new SimpleAuthenticationInfo(user, user.getPasswd(), this.getName());
                return simpleAuthenticationInfo;
            }
        }
    }
}


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月15日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2024年05月31日   24   0   0 redis用户
  TEZNKK3IfmPf   2024年05月31日   27   0   0 dataredis
  TEZNKK3IfmPf   2024年05月31日   23   0   0 awkredis
  TEZNKK3IfmPf   2024年04月19日   35   0   0 javarediskey
TEZNKK3IfmPf