環境
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,首次登錄會慢一下