當前位置:首頁 » 操作系統 » sso源碼

sso源碼

發布時間: 2025-03-05 01:28:25

『壹』 單點登錄SSO原理和實現

歡迎大家關注?github.com/hsfxuebao?,希望對大家有所幫助,要是覺得可以的話麻煩給點一下Star哈

1. 單系統登錄機制1.1 http無狀態協議

web應用採用browser/server架構,http作為通信協議。http是無狀態協議,瀏覽器的每一次請求,伺服器會獨立處理,不與之前或之後的請求產生關聯,這個過程用下圖說明,三次請求/響應對之間沒有任何聯系

但這也同時意味著,任何用戶都能通過瀏覽器訪問伺服器資源,如果想保護伺服器的某些資源,必須限制瀏覽器請求;要限制瀏覽器請求,必須鑒別瀏覽器請求,響應合法請求,忽略非法請求;要鑒別瀏覽器請求,必須清楚瀏覽器請求狀態。既然http協議無狀態,那就讓伺服器和瀏覽器共同維護一個狀態吧!這就是會話機制

1.2 會話機制

瀏覽器第一次請求伺服器,伺服器創建一個會話,並將會話的id作為響應的一部分發送給瀏覽器,瀏覽器存儲會話id,並在後續第二次和第三次請求中帶上會話id,伺服器取得請求中的會話id就知道是不是同一個用戶了,這個過程用下圖說明,後續請求與第一次請求產生了關聯

伺服器在內存中保存會話對象,瀏覽器怎麼保存會話id呢?你可能會想到兩種方式:

請求參數

cookie

將會話id作為每一個請求的參數,伺服器接收請求自然能解析參數獲得會話id,並藉此判斷是否來自同一會話,很明顯,這種方式不靠譜。那就瀏覽器自己來維護這個會話id吧,每次發送http請求時瀏覽器自動發送會話id,cookie機制正好用來做這件事。cookie是瀏覽器用來存儲少量數據的一種機制,數據以」key/value「形式存儲,瀏覽器發送http請求時自動附帶cookie信息

tomcat會話機制當然也實現了cookie,訪問tomcat伺服器時,瀏覽器中可以看到一個名為「JSESSIONID」的cookie,這就是tomcat會話機制維護的會話id,使用了cookie的請求響應過程如下圖

1.3 登錄狀態

有了會話機制,登錄狀態就好明白了,我們假設瀏覽器第一次請求伺服器需要輸入用戶名與密碼驗證身份,伺服器拿到用戶名密碼去資料庫比對,正確的話說明當前持有這個會話的用戶是合法用戶,應該將這個會話標記為「已授權」或者「已登錄」等等之類的狀態,既然是會話的狀態,自然要保存在會話對象中,tomcat在會話對象中設置登錄狀態如下

HttpSession?session?=?request.getSession();session.setAttribute("isLogin",?true);

用戶再次訪問時,tomcat在會話對象中查看登錄狀態

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");

實現了登錄狀態的瀏覽器請求伺服器模型如下圖描述

每次請求受保護資源時都會檢查會話對象中的登錄狀態,只有 isLogin=true 的會話才能訪問,登錄機制因此而實現。

2. 多系統的復雜性

web系統早已從久遠的單系統發展成為如今由多系統組成的應用群,面對如此眾多的系統,用戶難道要一個一個登錄、然後一個一個注銷嗎?就像下圖描述的這樣

web系統由單系統發展成多系統組成的應用群,復雜性應該由系統內部承擔,而不是用戶。無論web系統內部多麼復雜,對用戶而言,都是一個統一的整體,也就是說,用戶訪問web系統的整個應用群與訪問單個系統一樣,登錄/注銷只要一次就夠了

2.1 為什麼會出現跨域問題

瀏覽器從一個域名的網頁去請求另一個域名的資源時,域名、埠、協議任一不同,都是跨域。在前後端分離的模式下,前後端的域名是不一致的,此時就會發生跨域訪問問題。在請求的過程中我們要想回去數據一般都是post/get請求,所以..跨域問題出現。出於瀏覽器的同源策略限制。

同源策略(Sameoriginpolicy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。

可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。

同源策略會阻止一個域的javascript腳本和另外一個域的內容進行交互。

所謂同源(即指在同一個域)就是兩個頁面具有相同的協議(protocol),主機(host)和埠號(port)

2.2 什麼是跨域

當一個請求 url 的協議、域名、埠三者之間任意一個與當前頁面 url 不同即為跨域

當前頁面url 被請求頁面url 是否跨域 原因

http://www.test.com/ 和?http://www.test.com/index.html ?否 同源(協議、域名、埠號相同)

http://www.test.com/ 和?https://www.test.com/index.html?跨域 協議不同(http/https)

http://www.test.com/ 和?網路一下,你就知道?跨域 主域名不同(test/)

http://www.test.com/? 和 http://blog.test.com/?跨域 子域名不同(www/blog)

http://www.test.com:8080/?和 http://www.test.com:7001/?跨域 埠號不同(8080/7001)

2.3 多系統解決方案

雖然單系統的登錄解決方案很完美,但對於多系統應用群已經不再適用了,為什麼呢?

單系統登錄解決方案的核心是cookie,cookie攜帶會話id在瀏覽器與伺服器之間維護會話狀態。但cookie是有限制的,這個限制就是cookie的域(通常對應網站的域名),瀏覽器發送http請求時會自動攜帶與該域匹配的cookie,而不是所有cookie

既然這樣,為什麼不將web應用群中所有子系統的域名統一在一個頂級域名下,例如「*..com」,然後將它們的cookie域設置為「.com」,這種做法理論上是可以的,甚至早期很多多系統登錄就採用這種同域名共享cookie的方式。然而,可行並不代表好,共享cookie的方式存在眾多局限:

首先,應用群域名得統一;

其次,應用群各系統使用的技術(至少是web伺服器)要相同,不然cookie的key值(tomcat為JSESSIONID)不同,無法維持會話,共享cookie的方式是無法實現跨語言技術平台登錄的,比如java、php、.net系統之間;

第三,cookie本身不安全。

因此,我們需要一種全新的登錄方式來實現多系統應用群的登錄,這就是單點登錄

3. 單點登錄

什麼是單點登錄?單點登錄全稱Single Sign On(以下簡稱SSO),是指在多系統應用群中登錄一個系統,便可在其他所有系統中得到授權而無需再次登錄,包括單點登錄與單點注銷兩部分

3.1 登錄

相比於單系統登錄,sso需要一個獨立的認證中心,只有認證中心能接受用戶的用戶名密碼等安全信息,其他系統不提供登錄入口,只接受認證中心的間接授權。間接授權通過令牌實現,sso認證中心驗證用戶的用戶名密碼沒問題,創建授權令牌,在接下來的跳轉過程中,授權令牌作為參數發送給各個子系統,子系統拿到令牌,即得到了授權,可以藉此創建局部會話,局部會話登錄方式與單系統的登錄方式相同。這個過程,也就是單點登錄的原理,用下圖說明

下面對上圖簡要描述:

用戶訪問系統1的受保護資源,系統1發現用戶未登錄,跳轉至sso認證中心,並將自己的地址作為參數

sso認證中心發現用戶未登錄,將用戶引導至登錄頁面

用戶輸入用戶名密碼提交登錄申請

sso認證中心校驗用戶信息,創建用戶與sso認證中心之間的會話,稱為全局會話,同時創建授權令牌

sso認證中心帶著令牌跳轉會最初的請求地址(系統1)

系統1拿到令牌,去sso認證中心校驗令牌是否有效

sso認證中心校驗令牌,返回有效,注冊系統1

系統1使用該令牌創建與用戶的會話,稱為局部會話,返回受保護資源

用戶訪問系統2的受保護資源

系統2發現用戶未登錄,跳轉至sso認證中心,並將自己的地址作為參數

sso認證中心發現用戶已登錄,跳轉回系統2的地址,並附上令牌

系統2拿到令牌,去sso認證中心校驗令牌是否有效

sso認證中心校驗令牌,返回有效,注冊系統2

系統2使用該令牌創建與用戶的局部會話,返回受保護資源

用戶登錄成功之後,會與sso認證中心及各個子系統建立會話,用戶與sso認證中心建立的會話稱為全局會話,用戶與各個子系統建立的會話稱為局部會話,局部會話建立之後,用戶訪問子系統受保護資源將不再通過sso認證中心,全局會話與局部會話有如下約束關系:

局部會話存在,全局會話一定存在

全局會話存在,局部會話不一定存在

全局會話銷毀,局部會話必須銷毀

你可以通過博客園、網路、csdn、淘寶等網站的登錄過程加深對單點登錄的理解,注意觀察登錄過程中的跳轉url與參數

3.2 注銷

單點登錄自然也要單點注銷,在一個子系統中注銷,所有子系統的會話都將被銷毀,用下面的圖來說明

sso認證中心一直監聽全局會話的狀態,一旦全局會話銷毀,監聽器將通知所有注冊系統執行注銷操作

下面對上圖簡要說明:

用戶向系統1發起注銷請求

系統1根據用戶與系統1建立的會話id拿到令牌,向sso認證中心發起注銷請求

sso認證中心校驗令牌有效,銷毀全局會話,同時取出所有用此令牌注冊的系統地址

sso認證中心向所有注冊系統發起注銷請求

各注冊系統接收sso認證中心的注銷請求,銷毀局部會話

sso認證中心引導用戶至登錄頁面

4. 實現

只是簡要介紹下基於java的實現過程,不提供完整源碼,明白了原理,我相信你們可以自己實現。sso採用客戶端/服務端架構,我們先看sso-client與sso-server要實現的功能(下面:sso認證中心=sso-server)

sso-client:

攔截子系統未登錄用戶請求,跳轉至sso認證中心

接收並存儲sso認證中心發送的令牌

與sso-server通信,校驗令牌的有效性

建立局部會話

攔截用戶注銷請求,向sso認證中心發送注銷請求

接收sso認證中心發出的注銷請求,銷毀局部會話

sso-server:

驗證用戶的登錄信息

創建全局會話

創建授權令牌

與sso-client通信發送令牌

校驗sso-client令牌有效性

系統注冊

接收sso-client注銷請求,注銷所有會話

接下來,我們按照原理來一步步實現sso吧!

4.1 sso-client攔截未登錄請求

java攔截請求的方式有servlet、filter、listener三種方式,我們採用filter。在sso-client中新建LoginFilter.java類並實現Filter介面,在doFilter()方法中加入對未登錄用戶的攔截

public?void?doFilter(ServletRequest?request,?ServletResponse?response,?FilterChain?chain)?throws?IOException,?ServletException?{????HttpServletRequest?req?=?(HttpServletRequest)?request;????HttpServletResponse?res?=?(HttpServletResponse)?response;????HttpSession?session?=?req.getSession();????if?(session.getAttribute("isLogin"))?{????????chain.doFilter(request,?response);????????return;????}????//跳轉至sso認證中心????res.sendRedirect("sso-server-url-with-system-url");}4.2 sso-server攔截未登錄請求

攔截從sso-client跳轉至sso認證中心的未登錄請求,跳轉至登錄頁面,這個過程與sso-client完全一樣

4.3 sso-server驗證用戶登錄信息

用戶在登錄頁面輸入用戶名密碼,請求登錄,sso認證中心校驗用戶信息,校驗成功,將會話狀態標記為「已登錄」

@RequestMapping("/login")public?String?login(String?username,?String?password,?HttpServletRequest?req)?{????this.checkLoginInfo(username,?password);????req.getSession().setAttribute("isLogin",?true);????return?"success";}4.4、sso-server創建授權令牌

授權令牌是一串隨機字元,以什麼樣的方式生成都沒有關系,只要不重復、不易偽造即可,下面是一個例子

String?token?=?UUID.randomUUID().toString();4.5、sso-client取得令牌並校驗

sso認證中心登錄後,跳轉回子系統並附上令牌,子系統(sso-client)取得令牌,然後去sso認證中心校驗,在LoginFilter.java的doFilter()中添加幾行

//?請求附帶token參數String?token?=?req.getParameter("token");if?(token?!=?null)?{????//?去sso認證中心校驗token????boolean?verifyResult?=?this.verify("sso-server-verify-url",?token);????if?(!verifyResult)?{????????res.sendRedirect("sso-server-url");????????return;????}????chain.doFilter(request,?response);}

verify()方法使用httpClient實現,這里僅簡略介紹,httpClient詳細使用方法請參考官方文檔

HttpPost?httpPost?=?new?HttpPost("sso-server-verify-url-with-token");HttpResponse?httpResponse?=?httpClient.execute(httpPost);4.6 sso-server接收並處理校驗令牌請求

用戶在sso認證中心登錄成功後,sso-server創建授權令牌並存儲該令牌,所以,sso-server對令牌的校驗就是去查找這個令牌是否存在以及是否過期,令牌校驗成功後sso-server將發送校驗請求的系統注冊到sso認證中心(就是存儲起來的意思)

令牌與注冊系統地址通常存儲在key-value資料庫(如redis)中,redis可以為key設置有效時間也就是令牌的有效期。redis運行在內存中,速度非常快,正好sso-server不需要持久化任何數據。

令牌與注冊系統地址可以用下圖描述的結構存儲在redis中,可能你會問,為什麼要存儲這些系統的地址?如果不存儲,注銷的時候就麻煩了,用戶向sso認證中心提交注銷請求,sso認證中心注銷全局會話,但不知道哪些系統用此全局會話建立了自己的局部會話,也不知道要向哪些子系統發送注銷請求注銷局部會話

4.7 sso-client校驗令牌成功創建局部會話

令牌校驗成功後,sso-client將當前局部會話標記為「已登錄」,修改LoginFilter.java,添加幾行

if?(verifyResult)?{????session.setAttribute("isLogin",?true);}

sso-client還需將當前會話id與令牌綁定,表示這個會話的登錄狀態與令牌相關,此關系可以用java的hashmap保存,保存的數據用來處理sso認證中心發來的注銷請求

4.8、注銷過程

用戶向子系統發送帶有「logout」參數的請求(注銷請求),sso-client攔截器攔截該請求,向sso認證中心發起注銷請求

String?logout?=?req.getParameter("logout");if?(logout?!=?null)?{????this.ssoServer.logout(token);}

sso認證中心也用同樣的方式識別出sso-client的請求是注銷請求(帶有「logout」參數),sso認證中心注銷全局會話

@RequestMapping("/logout")public?String?logout(HttpServletRequest?req)?{????HttpSession?session?=?req.getSession();????if?(session?!=?null)?{????????session.invalidate();//觸發LogoutListener????}????return?"redirect:/";}

sso認證中心有一個全局會話的監聽器,一旦全局會話注銷,將通知所有注冊系統注銷

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");05. 快速接入SSO5.1 xxl-sso特性

簡潔:API直觀簡潔,可快速上手

輕量級:環境依賴小,部署與接入成本較低

單點登錄:只需要登錄一次就可以訪問所有相互信任的應用系統

分布式:接入SSO認證中心的應用,支持分布式部署

HA:Server端與Client端,均支持集群部署,提高系統可用性

跨域:支持跨域應用接入SSO認證中心

Cookie+Token均支持:支持基於Cookie和基於Token兩種接入方式,並均提供Sample項目

Web+APP均支持:支持Web和APP接入

實時性:系統登陸、注銷狀態,全部Server與Client端實時共享

CS結構:基於CS結構,包括Server"認證中心"與Client"受保護應用"

記住密碼:未記住密碼時,關閉瀏覽器則登錄態失效;記住密碼時,支持登錄態自動延期,在自定義延期時間的基礎上,原則上可以無限延期

路徑排除:支持自定義多個排除路徑,支持Ant表達式,用於排除SSO客戶端不需要過濾的路徑

5.2 環境

JDK:1.7+

Redis:4.0+

5.3 下載xxl-sso源碼源碼倉庫地址Release Downloadgithub.com/xuxueli/xxl…Downloadgitee.com/xuxueli0323…Download5.4 文檔地址

中文文檔

5.5 項目結構說明HttpSession?session?=?request.getSession();session.getAttribute("isLogin");15.6 基於Token方式部署

由於前後端分離開發的模式較多,這里只介紹基於Token方式部署,在一些無法使用Cookie的場景下,可使用該方式,如需要Cookie查看基於cookie方式部署

5.6.1 認證中心(SSO Server)搭建

項目名:xxl-sso-server

配置文件位置:application.properties

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");25.6.2 單點登陸Client端搭建

項目名:xxl-sso-token-sample-springboot

maven依賴

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");3

配置文件:application.properties

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");4

配置 XxlSsoTokenFilter

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");55.6.3 驗證 (模擬請求 Token 方式接入SSO的介面)

修改Host文件:域名方式訪問認證中心,模擬跨域與線上真實環境

HttpSession?session?=?request.getSession();session.getAttribute("isLogin");6

分別運行 "xxl-sso-server" 與 "xxl-sso-token-sample-springboot"

認證中心搭建成功後,默認為Token方式登陸提供API介面:

1、登陸介面:/app/login

code:200 表示成功、其他失敗

msg:錯誤提示

data: 登陸用戶的 sso sessionid

username:賬號

password:賬號

參數:POST參數

響應:JSON格式

2、注銷介面:/app/logout

code:200 表示成功、其他失敗

msg:錯誤提示

sessionId:登陸用戶的 sso sessionid

參數:POST參數

響應:JSON格式

3、登陸狀態校驗介面:/app/l

『貳』 一些推薦的CCFCSP認證試題參考網址

首先貼上歷年真題刷題網址,就是在官網上哈
http://118.190.20.162/
https://passport.ccf.org.cn/sso/login?from===

其實kuangbin那本書還有點看不懂,附上其它的演算法模板
演算法褲老模胡扒升板

源碼:
學院老師寫的
github中找到的好東西

學院大佬們和老師的鏈接,菜雞學弟眯著眼偷偷看此拿嘿嘿
https://blog.csdn.net/wl16wzl
https://blog.csdn.net/tigerisland45
https://blog.csdn.net/Miranda_ymz
https://me.csdn.net/cfarmerreally

熱點內容
C編譯多個 發布:2025-03-05 05:21:16 瀏覽:506
ftp有cd命令嗎 發布:2025-03-05 04:47:20 瀏覽:574
雲伺服器比物理機的優勢 發布:2025-03-05 04:46:05 瀏覽:466
俺媽密碼是什麼 發布:2025-03-05 04:40:46 瀏覽:159
yacclex編譯器 發布:2025-03-05 04:35:37 瀏覽:151
安卓相片怎麼轉另一個手機 發布:2025-03-05 04:23:40 瀏覽:545
解壓要素 發布:2025-03-05 04:16:05 瀏覽:791
觀致網路模塊怎麼接入安卓車機 發布:2025-03-05 03:53:40 瀏覽:462
安卓如何被冥龍鎖定後免傷 發布:2025-03-05 03:49:13 瀏覽:969
標准sql語言 發布:2025-03-05 03:42:51 瀏覽:302