栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

账号多端限制登录。用户使用同一个账号登录,后面登录的会把前面登录的挤下线。shiro+ehcache

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

账号多端限制登录。用户使用同一个账号登录,后面登录的会把前面登录的挤下线。shiro+ehcache

思路:

用户登录信息存放缓存ehCache,调用登录接口之前,从缓存获取系统当前在线用户数据,数据包含sessionId和账号。如果当前登录账号和获取的在线用户的账号相同,则把这个账号的sessionId的timeout设置为1秒。

 1. 配置EhCache

将EhCache与SpringBoot整合在一起,这其中就要装配两个重要的bean[EhCacheManagerFactoryBean]和[EhCacheManager] 

@Configuration
public class ShiroConfiguration {
    public ShiroConfiguration() {
    }
    
    //配置缓存信息ehcach.xml
    @Bean(name = {"ehCacheManagerFactoryBean"})
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() {
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ClassPathResource classPathResource = new ClassPathResource("cache/ehcache-local.xml");
        ehCacheManagerFactoryBean.setConfigLocation(classPathResource);
        return ehCacheManagerFactoryBean;
    }    

    //缓存管理器
    @Bean(name = {"shiroCacheManager"})
    public EhCacheManager shiroCacheManager() {
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(this.ehCacheManagerFactoryBean.getObject());
        return ehCacheManager;
    }

    @Bean(name = {"securityManager"})
    public SecurityManager securityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //授权域。继承AuthorizingRealm重写doGetAuthenticationInfo认证、doGetAuthorizationInfo授权
        defaultWebSecurityManager.setRealm(*****);
        defaultWebSecurityManager.setSessionManager(this.getDefaultWebSessionManager());
        defaultWebSecurityManager.setCacheManager(this.shiroCacheManager());
        SecurityUtils.setSecurityManager(defaultWebSecurityManager);
        return defaultWebSecurityManager;
    }

    @Bean(name = {"defaultWebSessionManager"})
    public DefaultWebSessionManager getDefaultWebSessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setGlobalSessionTimeout(3600000L);
        sessionManager.setDeleteInvalidSessions(true);
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setDeleteInvalidSessions(true);    
        sessionManager.setSessionIdCookieEnabled(true);
        sessionManager.setSessionDAO(this.sessionDao());
        sessionManager.setCacheManager(this.shiroCacheManager());
        return sessionManager;
    }

    @Bean(name = {"sessionDao"})
    public EnterpriseCacheSessionDAO sessionDao() {
        EnterpriseCacheSessionDAO sessionDao = new EnterpriseCacheSessionDAO();
        //存放session的ehcache名称
        sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache");
        //sessionId生成规则,查看源码实际上就是UUID.randomUUID().toString()
        sessionDao.setSessionIdGenerator(new JavaUuidSessionIdGenerator());
        return sessionDao;
    }

}

 2. 调用登录接口前获取当前在线用户信息

public OnlineUserVO getOnlineUser() {
        Set userIdSet = new HashSet();
        OnlineUserVO onlineUserVO = new OnlineUserVO();
        List onlineUserEOList = new ArrayList();
        //获取当前所有活跃用户
        Collection sessions = this.sessionDAO.getActiveSessions();
        Iterator var5 = sessions.iterator();

        while(var5.hasNext()) {
            Object sessionObject = var5.next();
            if (sessionObject instanceof SimpleSession) {
                SimpleSession simpleSession = (SimpleSession)sessionObject;
                Object object = simpleSession.getAttribute("LOGIN_USER");
                if (null != object) {
                    UserEO userEO = (UserEO)object;
                    if (!userIdSet.add(userEO.getUsid())) {
                        break;
                    }

                    OnlineUserEO onlineUserEO = new OnlineUserEO();
                    onlineUserEO.setAccount(userEO.getAccount());
                    onlineUserEO.setIp(simpleSession.getHost());
                    onlineUserEO.setLoginTime(simpleSession.getStartTimestamp());
                    onlineUserEO.setSessionId(simpleSession.getId().toString());
                    onlineUserEOList.add(onlineUserEO);
                }
            }
        }
        onlineUserVO.setOnlineUsers(onlineUserEOList);
        onlineUserVO.setTotal(onlineUserEOList.size());
        return onlineUserVO;
}

在第一步配置EhCache信息时,sessionDao方法配置了缓存名称sessionDao.setActiveSessionsCacheName("shiro-activeSessionCache");

返回的数据包含sessionId

3. 用huihua

public void loginOutBySessionId(String sessionId) {
        Collection sessions = this.sessionDAO.getActiveSessions();
        Iterator var3 = sessions.iterator();

        while(var3.hasNext()) {
            Object sessionObject = var3.next();
            if (sessionObject instanceof SimpleSession) {
                SimpleSession simpleSession = (SimpleSession)sessionObject;
                if (StringUtils.equals(sessionId, simpleSession.getId().toString())) {
                    simpleSession.setTimeout(1000L);
                }
            }
        }

    }

 需要下线的账号的sessionId的会话时间设置为1000毫秒。

 4.  登录信息存放到ehCache缓存

//只展示核心内容
public Message login(HttpServletRequest request, UsernamePasswordToken token) {
    Subject subject = SecurityUtils.getSubject();
    //登录
    subject.login(token);
    Session session = subject.getSession(true);
    //获取当前登录用户信息
    UserEO userEO = UserUtils.getUser();
    session.setAttribute("LOGIN_USER", userEO);
    //获取用户的角色
    UserEO returnEO = this.userService.getRoles(userEO.getUsid());
    session.setAttribute("LOGIN_USER_ID", userEO.getUsid());
    session.setAttribute("LOGIN_ROLE_ID", UserUtils.getRoleIds());
    //把session信息存放ehcache
    if (null != session) {
       CacheUtils.putShiroSessionCache(userEO.getUsid(), session.getId());
    }

}

//获取当前登录用户信息
public static UserEO getUser() {
        //缓存获取用户信息
        UserEO user = (UserEO)CacheUtils.getCache("currentUser");
        if (user == null) {
            String userId = null;
            Subject subject = SecurityUtils.getSubject();
            MyPrincipal principal = (MyPrincipal)subject.getPrincipal();
            if (principal != null) {
                userId = principal.getId();
            }
            if (StringUtils.isNotEmpty(userId)) {
                //查询用户信息
                user = userService.getUser(userId);
                user.setPassword((String)null);
                //用户信息放缓存
                CacheUtils.putCache("currentUser", user);
            }
        }
        return user;
}
public class CacheUtils {
    
    public static void putShiroSessionCache(String key, Object value) {
        Element element = new Element(key, value);
        String cacheName = "shiro-activeSessionCache";
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            cacheManager.addCache(cacheName);
            cache = cacheManager.getCache(cacheName);
            cache.getCacheConfiguration().setEternal(true);
        }
        cache.put(element);
    }
    
    public static Object getCache(String key, Object defaultValue) {
            Object obj = getCacheMap().get(key);
            return obj == null ? defaultValue : obj;
    }

    //
    public static void putCache(String key, Object value) {
            getCacheMap().put(key, value);
        }

    public static Map getCacheMap() {
            HashMap map = Maps.newHashMap();
            try {
                Subject subject = SecurityUtils.getSubject();
                //MyPrincipal信息来源于realm中doGetAuthenticationInfo的new SimpleAuthenticationInfo()
                MyPrincipal principal = (MyPrincipal)subject.getPrincipal();
                return (Map)(principal != null ? principal.getCacheMap() : map);
            } catch (UnavailableSecurityManagerException var3) {
                UserUtils.logger.error("getCacheMap UnavailableSecurityManagerException", var3);
            } catch (InvalidSessionException var4) {
                UserUtils.logger.error("getCacheMap InvalidSessionException", var4);
            }
            return map;
        }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/885870.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号