Token方式单点登录流程

来自ling
跳转至: 导航搜索

主要原理

  • cookie是有范围和时间的 参考跨域(二级域)session共享#跨域共享cookie
  • 把session加密后存在cookie中,每次session信息被写在客服端,然后经浏览器再次提交到服务器.即使两次请求在集群中的两台服务器上完成,也可以到达session共享.这种解决方法的优点是session信息不用存放在服务器端,大大减轻了服务器的压力.另一个优点是一个session中的两次或多次请求可以在一个群集中的多个服务器上完成,可以避免单端故障,更多参考Java集群之session共享解决方案

token

如下图,请参考,整个过程由登录逻辑,模拟登录逻辑,登出逻辑,模拟登出逻辑和一个统一的filter完成

  • cookie和session中所放入的内容定义
  1. Cookie中建议存放token
  2. session中放入token和当前用户,机构,角色等java对象 更多参考HttpSession
  3. token中建议存放加密后的sid,token过期时间,用户名,机构id,token版本等简单内容
  • filter必须在filter链第一位
  • 不同的系统路径不一样,如何支持跨域
  1. 关于跨域,如果是ajax,拦截公共方法,将token添加到header中
  2. filter取token的值也是从header中获取
  • sid为登录时分配的用户在所有集群都一样的可用于缓存的用户当前登录唯一key
  • 允许token相同版本号上updateTime的时间误差(2个请求,先请求后响应时,后响应的token会覆盖先响应的token)
  • 更新token中的关键信息必须使token中的版本号加1,并且需要刷新整个浏览器的当前页面,避免后响应的token会覆盖先响应的token问题.比如JavaScript上通过window.url=index解决,java代码中不再处理
  • 如果有第三方缓存(比如Redis)来缓存用户信息.通过全局不变的sid和版本号可以有效解决2个请求,先请求后响应时,后响应的token会覆盖先响应的token问题

Token session1.png

关键代码

以下代码只依赖于session,和cookie,不依赖spring等第三方内容

BaseContextSecurity ContextFilter ContextHolder ContextUitls DefaultContextSecurity Token ContextSecurity

OAuth2

  1. 如果比较复杂的跨域就得使用oauth2

OAuth2.jpg

其他问题

  • ?如何判定用户是否有登录的session?
  1. Ibz的WebContext已提供相关方法
  2. 基本原理就是使用ThreadLocal<HttpSession>

private static final ThreadLocal<HttpSession> httpSessionThreadLocal = new ThreadLocal<HttpSession>(); httpSessionThreadLocal.set(request.getSession());