【JWT学习之二】JWT实现单点登录
环境
apache-tomcat-8.5.45
jdk1.8.0_65
java-jwt3.3.0
SpringBoot-2.1.3.RELEASE
一、需求背景
一个认证中心SSO:sso.cac2020.com
两个Java Web应用:
app1:app1.cac2020.com
app2:app2.cac2020.com
以上三个系统使用jwt实现单点登录。
二、架构设计图
使用Spring boot搭建示例工程:
参考:
三、JWT单点登录方案
1、方案
前端方案:不同域应用每次请求从localStorage里获取token作为url参数,然后应用使用拦截器校验token,然后向sso应用发起校验请求;(在浏览器中跨域将获取不到localstorage中的JWT令牌,例如www.a.com域下的JWT,在www.b.com域下是获取不到的,可以使用iframe+H5的postMessage实现跨域共享JWT,具体参考:浅谈postMessage跨域通信与localStorage实现跨域共享
后端方案:为一个唯一用户生成JWT,每个JWT生成一个随机的秘钥secret,将 jwt–secret 保存到redis中,想要让某个jwt失效,只需将该记录在 redis 中删除即可(这样在解密时便无法获取到 secret)。但是这样让无状态的认证机制变成有状态了(记录了 jwt 和 secret 的对应关系)
2、流程图:
首次访问app1流程:
app1:index.html-->app1:LoginFilter.java-->sso:checkJwt-->未登录app1:index.html-->sso:index.html-->sso:login.html-->sso:login-->app1:redirect.html-->app1:index.html
已登录app1再次访问app1:
app1:index.html-->app1:LoginFilter.java-->sso:checkJwt-->app1:index.html
已登录app1然后访问app2:
app2:index.html-->app2:LoginFilter.java-->sso:checkJwt-->app2:index.html
注销app1:
app1:index.html-->app1:LoginFilter.java-->app1:logout-->sso:inValid
3、验证
参考文章:
方案一:spring boot如何基于回调共享JWT实现单点登录详解
代码参考:wjy_parent
方案二:
方案特点:
(1)依赖JWT包生成工具类JWTHelper工具包;
(2)采用iframe+H5的postMessage解决页面跨域问题;
方案三
基于JWT的单点登录
本方案特点:
(1)使用cookie存储JWT,存在跨域问题;
(2)sso在首次生成JWT时将User相关信息存储到JWT里,应用侧获取到JWT解密JWT字符串获取User信息;
(3)sso和应用端使用同一个加密key,SSO侧使用加密key进行加密,应用端使用加密key进行紧密获取用户信息,如果泄露加密key就会产生安全问题。
方案四
java实现SSO单点登录(同父域跨域)
java实现 SSO 单点登录(不同父域跨域)
参考代码:github
方案特点:
方案特点:
(1)采用cookie存储JWT,页面跨域部分使用的是ajax的jsonp方式;
(2)将不同的域存到表里,然后首次登录成功之后,在页面循环调用各个域种下cookie,首次登录会慢一下