SSO原理解析

什麼是單點登陸

簡單點說就是公司有A,B兩個系統,我登陸了A系統以後再跳轉到B系統能夠直接訪問,而不須要再次登陸B系統.java

 

幾種常見的單點登陸實現方式

在講解單點登陸以前先講解幾個基本的概念:nginx

Cookie:

Cookie是一段不超過4KB的小型文本數據,是保存在用戶本地的,常見格式爲:web

 

Expires屬性:設置Cookie的生存期redis

 

Domain屬性:指定了能夠訪問該 Cookie 的 Web 站點或域跨域

好比圖中的Domain:192.168.1.72這就表示只能只有1.72下的請求可使用這個cookie,百度什麼的就不能使用這個cookie瀏覽器

 

Path屬性:定義了Web站點上能夠訪問該Cookie的目錄安全

圖中的Path是/,這表示這個cookie是根目錄擁有的,只要1.72的請求都會默認帶上這個cookie,加入Path是/webaikn,那麼只有http://192.168.1.72/webaikn/**的請求會帶上這個cookie,而http://192.168.1.72/webadmin/**就沒法使用這個cookie服務器

 

其餘:略cookie

 

Session:

http請求是無狀態的,可是咱們平常訪問系統的時候都是但願系統能記住我這個用戶,這時候就要靠session去實現,所以session成爲會話控制.可是光靠session仍是沒法實現會話控制的,還須要cookie的配置,如圖所示:session

 

 

 

這個JESSIONID就是保持會話的關鍵,它的value對應的就是該用戶在服務器的sessionId,因此咱們代碼直接寫HttpSession   session   =   request.getSession();  纔不會數據錯亂.

Ps:session的存在方便了咱們的開發,可是也在必定程度上增長了麻煩,好比多機部署時候的seesion丟失,

      

重定向

       一句話,轉發是服務器行爲,重定向是客戶端行爲.

      轉發和重定向均可以由java後臺實現,例如:

請求轉發:

request.getRequestDispatcher("/user").forward(request,response);

重定向:

response.sendRedirect(request.getContextPath + "/user")

 

當設置轉發以後,請求會直接去轉發的地址,而重定向的話請求會先返回客戶端,而後再由客戶端從新發起請求去新的地址.這裏就隱藏了一個知識點,當我在後臺設置了cookie而後重定向的時候,其實我重定向的請求中已經帶上了我設置的cookie

 

(1)   假設A和B兩個系統都部署在192.168.110.110服務器上

用戶在登陸了A系統以後,後臺代碼設置將userName和password做爲cookie存入到用戶的瀏覽器中並將cookie的domain設置爲192.168.110.110,path設置爲/

以後訪問B系統的時候因爲你們的Ip都是同樣的,因此B系統可以獲取到A系統設置的cookie,這是隻須要設置一個攔截器,在攔截器中判斷用戶是不是登陸狀態,若是未登陸就去request中獲取cookie信息,獲取到以後解密而後模擬登陸,這樣用戶能夠無感知的登陸到B系統.

 

點評:這是典型的同域單點登陸實現方式,侷限性很是大,必需要兩個系統在同一個服務器或者二級域名相同的狀況下才能實現,通常稱爲僞單點登陸

 

(2)   知識庫系統的單點登陸實現

知識庫的方案1的基礎上增長了Nginx做爲反向代理(有反向代理就有正向代理,自行查找資料什麼是正向代理什麼是反向代理)

 

 

 

 

雖然webaikn和webadmin部署在不一樣的服務器,可是對客戶是無感知的,因爲都是訪問Nginx,而後再由nginx作轉發代理,因此域名是同一個,這樣cookie也是能夠共享的,這裏有一個點須要注意一下,webaikn多是多機部署,因此nginx在作轉發的時候須要設置ip_hash策略,目的就是保證用戶上一次請求訪問的哪臺服務器,下一次仍是訪問那一臺服務器,不至於致使session丟失的狀況.   

 

 

 

 

點評:解決了多機部署單點登陸失效的狀況,可是仍是須要服務器端保存用戶的session狀態,一方面對於服務器端會產生內存壓力,另外一方面須要配置ip_hash致使流量不均衡,某些服務器壓力比較大的狀況.並且用戶名和密碼保存在cookie中也存在必定的安全隱患,只要被截取到一次請求都會形成帳戶被盜的狀況

 

(3)   跨域token實現單點登陸

主要步驟:

  1. 用戶登陸A系統,A系統攔截器發現請求沒有帶token,因而重定向到單點登陸認證中心sso系統,注意帶上用戶以前請求的url,咱們後面就叫oldUrl
  2. Sso接收到請求,發現request的cookie中沒有登陸成功的令牌token,因而重定向到本系統的登陸頁面,繼續帶着oldUrl
  3. 用戶輸入用戶名和密碼,提交
  4. Sso驗證用戶名是否正確,不正確繼續重定向到登陸頁面,若是正確,進行下面的操做:

生成一個cookie,name就叫token,value能夠是任意不重複的值,uuid就行(注意這個cookie是瀏覽器和sso系統之間的)

將用戶信息保存到redis中,key是生成的uuid,value就是user對象

重定向到oldUrl的地址,注意要拼接上token參數

  1. A系統再次收到請求,不一樣的是此次有token參數,A系統根據token的值去redis驗證,這裏須要分狀況討論了

 沒有找到:說明其餘子系統發起了註銷操做,須要重定向到sso登陸頁面

 找到了:有了User對象以後能夠判斷當前請求是否在用戶權限表中,存在就直接放行,不存在返回權限不足,以後的請求都須要將token放到請求頭信息或者url中

  1. 用戶瀏覽完A系統以後,準備去B系統轉轉,因而瀏覽器向B系統發起請求,B系統攔截器收到請求,發現請求沒有帶token,發起重定向去sso,記得帶上本次請求的oldUrl
  2. 這時候其實和上面的第二步差很少,區別在於因爲以前登陸過sso因此此次的request中是有token的cookie的,因此sso只須要重定向到oldUrl指向的地址就行,同時記得將cookie中取出來的token拼接到url中
  3. B再次系統收到請求,以後的操做和步驟5是同樣的了

 

點評:獨立出單點登陸認證中心,統一作權限認證操做,清晰明瞭

子系統不須要用session保存用戶登陸狀態,減輕了服務器的負擔

每次請求都是以token做爲驗證標準,就算請求被攔截了,用戶的信息也不會泄露

後期作三方登陸的時候也不須要將用戶數據暴露給其餘系統,其餘系統能獲取的只有token(真要作三方登陸redis中存放的確定是最簡單的一些用戶信息)

下面這個圖取自哪位大佬我已經沒有地址了,好像是百寶門

 

相關文章
相關標籤/搜索