Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前后端分离下的用户认证和鉴权实践(五) 用户登录状态的保持和单点登录 #6

Open
ZhuXS opened this issue Oct 16, 2017 · 4 comments

Comments

@ZhuXS
Copy link
Owner

ZhuXS commented Oct 16, 2017

用户登录状态的保持和单点登录

  • 服务器应该对用户的登录状态有保持机制。即在用户登录成功之后的一段时间内,用户无需重复登录即可访问权限允许的接口
  • 在有多个应用服务器的情况下,用户的登录状态能够在多个互相信任的服务器之间共享(即单点登录)

挑战

  • Http请求是无状态的,协议对于事务处理没有记忆能力,人生只若初见
  • 多台硬件服务器之间的缓存无法共享
  • 用户的权限和角色信息如何体现在请求中

解决方案

  • 利用Session机制,浏览器端发送的请求携带一个SessionId
  • 将用户的权限和角色信息存储到session之中
  • Session缓存到Redis中,在服务器集群之间共享

实现

  • shiro简介中提到,SecurityManager引用了多个安全管理组件,其中就包括SessionManager,即会话管理器
  • SessionManager要设置相应SessionFactory和SessionDao
    @Bean(name = "sessionManager")
        public DefaultWebSessionManager sessionManager(){
            DefaultWebSessionManager manager = new DefaultWebSessionManager();
            //manager.setCacheManager(cacheManager);// 加入缓存管理器
            manager.setSessionFactory(shiroSessionFactory());//设置sessionFactory
            manager.setSessionDAO(shiroSessionDao());// 设置SessionDao
            manager.setDeleteInvalidSessions(true);// 删除过期的session
            manager.setGlobalSessionTimeout(shiroSessionDao().getExpireTime());// 设置全局session超时
    时间
            manager.setSessionValidationSchedulerEnabled(true);// 是否定时检查session
            return manager;
        }
  • SessionFactory负责生成自定义的Session
  • SessionDao中规定了session的CRUD操作,也正是在这里将Session存储到Redis中
    @Override
      protected Serializable doCreate(Session session) {
          Serializable sessionId = this.generateSessionId(session);
          assignSessionId(session,sessionId);
          Jedis jedis = null;
          try{
              jedis = jedisPool.getResource();
              //session由Redis缓存失效决定,这里作简单标识
              session.setTimeout(expireTime);
              jedis.setex(prefix + sessionId, expireTime, SerializeUtils.serializaToString((ShiroSession) session));
              logger.info("sessionId {} name {} 被创建", sessionId, session.getClass().getName());
          }catch (Exception e){
              logger.warn("创建session失败",e);
          }finally {
              jedis.close();
          }
          return sessionId;
      }
    • doUpdate(),更新session 时执行
    • doDelete(),删除Session时执行
    • doReadSession,读取Session时执行

优势

  • 用户不必重复登录以获取权限
  • 用户的Session在多个服务器之间共享,实现单点登录
@Zhouwt998
Copy link

您可以提供一下RedisCache类给我看看吗

@alexpdh
Copy link

alexpdh commented May 2, 2018

请问一下你们有实现单点的功能吗,我们现在想集成cas+shiro,但是前后端分离我们没有找到解决方案,不知道您这边有没有什么解决方案没有?还望赐教,感谢!

@ZhuXS
Copy link
Owner Author

ZhuXS commented May 7, 2018

@alexpdh redis作为分布式缓存可以解决单点问题

@ZhuXS
Copy link
Owner Author

ZhuXS commented May 7, 2018

@Zhouwt998 你指的是哪个类

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants