> 演示Demo站點 http://sso.exrick.cn
# 前后端分離下單點登錄實現
| 單點登錄模式 | 優點 |缺點 |
| --- | --- | --- |
|共享Cookie模式 | 簡單方便,用戶體驗好 |根域名需限制一致;Cookie可能不安全|
|OAuth2.0模式 |靈活安全,不受站點限制 |成本稍高,需獨立的認證中心 |
|跨域設置Cookie |用戶體驗好,不受站點限制 |比較麻煩;Cookie可能不安全 |
|客戶端模式 |用戶體驗好,不受站點限制 |成本極高,依賴于用戶本地安裝客戶端應用 |
## 共享Cookie模式[【完整版】](http://xpay.exrick.cn/pay?xboot)
- 首先需進入“系統管理-系統配置”菜單中的“其他配置”設置你應用部署的一級域名,用戶登錄后將在該域名及子級域名下存儲Cookie令牌`accessToken`用于其他站點獲取接口,完整版用戶詳見`xboot-sso`項目。
- 其他站點從Cookie中取出`accessToken`即`Cookies.get("accessToken")`即可攜帶上`accessToken`請求其他接口,通常用于內部信任的站點
<img src="https://ooo.0o0.ooo/2019/08/19/yrgX4fdOhUSincs.png" width="600px">
## OAuth2.0模式
### 認證中心
- 即通過平臺的獨立統一認證站點完成身份認證,其他站點通過獲取access_token完成授權以及之后的請求鑒權
- XBoot統一認證地址: 運行前端,路由地址為`/authorize`,默認即 http://127.0.0.1:9999/authorize, 在線demo地址 http://xboot.exrick.cn/authorize
### 單點登錄流程分析示例
> 兩三句話就能講明白的事情,網上的大多資料畫再復雜的時序圖也講不清關鍵點
- 站點1發現用戶未登錄時,跳轉至認證中心
- 認證中心發現用戶未登錄(Cookie中沒有認證記錄),顯示認證中心的登錄頁面
- 用戶輸入賬號密碼登錄,認證成功后,**前端記錄認證信息保存后端返回的accessToken令牌(可通過令牌獲取對應用戶名username)**,后端Redis存入access_token對應信息,其key為`username:站點1的clientId`,返回站點1的access_token
- 認證中心攜帶access_token跳轉至站點1的回調地址
- 站點1前端獲取到access_token令牌,記錄已登錄狀態,每次請求攜帶access_token
---
- 站點2發現用戶未登錄時,跳轉至認證中心
- 認證中心前端判斷已認證授權過:**從前端Cookie中取出存儲的accessToken(可通過令牌獲取對應用戶名username)**
- 認證中心調用已授權驗證接口,先驗證accessToken是否有效,若有效,則后端Redis存入新站點的access_token信息,其key為`username:站點2的clientId`,返回站點2的access_token
- 認證中心攜帶access_token跳轉至站點2的回調地址
- 站點2前端獲取到access_token令牌,記錄已登錄狀態,每次請求攜帶access_token
### 注銷流程分析示例
- 任一站點用戶退出登錄,通過Redis失效所有以`username`開頭的鍵值對即可
### 實現細節補充
- 認證中心可通過clientId可獲取站點的基本信息數據
### 退出登錄接口
- `/xboot/oauth2/logout`
- 需要攜帶主站的`accessToken`,通常為信任的內部站點中使用,將刪除失效當前用戶登錄的`accessToken`以及當前用戶授權第三方應用的`access_token`
### 自動授權說明
- 設置為自動授權后
<img src=https://s1.ax1x.com/2020/05/27/tk71Fs.png width=400/>
- 已認證登錄的用戶**不會**看到以下授權確認頁面,將自動授權跳轉。通常用于內部信任的站點以及單點登錄的實現
<img src=https://s1.ax1x.com/2020/05/27/tk7IfI.png width=400/>
## 跨域設置Cookie模式
> 淘寶、京東采用的方式
- 完全跨域的情況下`a.com`是肯定不能直接在`b.com`下設置Cookie的,那怎么辦?
- **開放設置Cookie接口**。b站點提供一個能在其站點下設置其Cookie的GET接口或JS腳本,供其他信任的站點如a站點調用
- 用戶先在a站點登錄成功后,通知調用其他站點的接口,為其他站點設置上Cookie,實現單點登錄
- 核心技術點:**利用GET請求加載靜態資源無跨域限制(無同源限制)**,即JSONP的原理
``` javascript
// a站點中將令牌給b站點
<script type="text/javascript" src="http://b.com/setCookie?accessToken=令牌"/>
// 動態創建
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://b.com/setCookie?accessToken=令牌';
document.head.appendChild(script);
```
- Github上也有一些JSONP的庫,如 [https://github.com/webmodules/jsonp](https://github.com/webmodules/jsonp)
~~~shell
$ npm install jsonp --save
~~~
~~~js
const jsonp = require('jsonp');
jsonp('http://b.com/setCookie?accessToken=令牌', null, (err, data) => {
if (err) {
console.error(err.message);
} else {
console.log(data);
}
});
~~~
- 退出登錄同理,調用退出登錄接口后端清除會話后,獲得要清空的其他站點列表,依次調用清除前端Cookie
- 當然這中間還涉及很多安全校驗,此處不再贅述
## 客戶端單點登錄模式
> QQ客戶端單點登錄流程分析
- 當本機電腦上啟動了QQ客戶端,再使用瀏覽器訪問QQ相關站點,如QQ郵箱,會顯示我們已經登錄了的QQ賬號信息提供快速登錄
<img src=https://s1.ax1x.com/2020/05/27/tEIL7Q.png width=300/>
- 其關鍵原理為QQ客戶端**內置一了個小型的 Web Server監聽了4301端口**,并提供當前登錄QQ信息的接口
- 訪問QQ郵箱登錄頁后會生成校驗參數去訪問這 Web Server提供的接口,實際地址為`https://localhost.ptlogin2.qq.com:4301/`,這個域名指向的是 127.0.0.1,可以解決Cookie跨域等權限問題
```js
請求
GET https://localhost.ptlogin2.qq.com:4301/pt_get_uins?callback=ptui_getuins_CB&r=0.5658049977525998&pt_local_tk=-440325439
響應
var var_sso_uin_list=[{"uin":1012139570,"face_index":-1,"gender":0,"nickname":"Exrick","client_type":66818,"uin_flag":8388612,"account":1012139570}];ptui_getuins_CB(var_sso_uin_list);
```
- 由于QQ有龐大的用戶基群并且能保證大部分人安裝使用QQ客戶端,因此通過該方式為用戶提供了便利
- 前言&版本說明
- 概念
- XBoot 是什么?
- 系統架構
- 主要使用的開源組件
- 角色控制訪問權限(RBAC)
- 用戶手冊
- 系統配置
- 工作流使用配置
- 定時任務調度
- 智能助手客服機器人
- 項目本地運行
- 后端運行
- 前端運行
- 項目結構說明
- 附:使用Oracle等數據庫
- 模塊化版本
- 后端開發指南
- 基本開發指南
- 前后端數據交互標準
- 工具類及數據權限
- 代碼生成器-30秒搞定CRUD
- 增刪改查CRUD
- 日志類型注解擴展
- 邏輯刪除
- 各驗證碼使用及配置
- 接口文檔使用及認證
- 前端開發指南
- 基本開發指南
- 主題/Logo/首頁等配置
- 路由菜單配置
- 多語言國際化配置
- 自定義圖標icon
- 工具類及數據獲取
- 其他說明
- 完整版開發指南
- 前端Vue代碼生成器
- Activiti工作流
- 單點登錄配置
- 智能助手/客服機器人
- MinIO對象存儲服務搭建
- 第三方社交賬號配置
- 短信開發/站內消息/郵件
- Vaptcha驗證碼
- 禁用詞使用
- 前端移除CDN
- 其他說明
- 開放平臺及單點登錄
- 開放平臺使用指南
- Web接入開發流程
- 單點登錄開發指南
- 微信小程序端開發指南
- 項目導入與開發必讀
- 業務組件
- 產品組件(小)
- 產品組件(大)
- 優惠券組件
- 評論列表組件
- 紅包組件
- 推薦商品組件
- 頁面設計
- 商品詳情頁及SKU設計
- 通用方法工具類說明
- 開發經驗與踩坑分享
- Uniapp端開發指南
- APP后端開發指南
- Uniapp前端開發指南
- 開發新功能示例
- 后端開發新模塊
- 前端開發新頁面
- 測試
- SonarQube代碼質量管理
- TestNG單元測試
- ExtentReports測試報告
- Selenuim自動化Web測試
- Appuim自動化App測試
- JMeter壓測性能測試
- 部署
- Spring Boot配置
- 快速部署
- 后端部署
- 前端部署
- 前端部署優化
- Docker容器化部署
- 服務器配置
- 持續集成
- GitLab
- GitLab CI
- XBoot 腳本參考
- Jenkins
- Jenkins安裝
- XBoot CI參考
- DevOps環境搭建
- 組件安裝列表
- 開發設計規范
- 分支管理
- 數據庫設計規范
- Redis使用規范
- Java基礎開發規范
- Rest API規范
- 項目結構規范
- 前端開發規范
- 前端設計規范
- 項目搭建分享
- 后端相關
- SpringBoot 2.x區別總結
- Spring Security整合JWT
- Spring Security動態權限管理
- Spring Boot 2.x整合Quartz
- Spring Boot 2.x整合Websocket
- Spring Boot 2.x整合Activiti工作流以及模型設計器
- Spring Boot + Security全局跨域配置
- 前端相關
- axios請求封裝 統一異常處理
- 動態路由菜單加載
- 多維度控制權限至按鈕顯示
- 發送消息圖標紅點實時顯示
- 動態組件單頁操作
- XBoot助你【告別996】
- 業務開發踩坑
- 你會用開發神器IDEA嗎
- Lombok你知道多少
- 你還在手動校驗參數嗎
- 你真的會用JPA嗎
- Lamda表達式
- Stream流式API
- 告別資源關閉
- Optional避免null
- 谷歌Guava工具包
- 線程池
- 其他小經驗技巧
- 更新日志及步驟
- 常見問題