天天看點

SSO單點登入統一身份認證系統

什麼是單點登入

簡單點說就是公司有A,B兩個系統,我登入了A系統之後再跳轉到B系統可以直接通路,而不需要再次登入B系統.

幾種常見的單點登入實作方式

在講解單點登入之前先講解幾個基本的概念:

Cookie:

Cookie是一段不超過4KB的小型文本資料,是儲存在使用者本地的,常見格式為:

SSO單點登入統一身份認證系統

Expires屬性:設定Cookie的生存期

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

其他:略

Session:

http請求是無狀态的,但是我們日常通路系統的時候都是希望系統能記住我這個使用者,這時候就要靠session去實作,是以session成為會話控制.但是光靠session還是無法實作會話控制的,還需要cookie的配置,如圖所示:

SSO單點登入統一身份認證系統

這個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作為反向代理(有反向代理就有正向代理,自行查找資料什麼是正向代理什麼是反向代理)

SSO單點登入統一身份認證系統

雖然webaikn和webadmin部署在不同的伺服器,但是對客戶是無感覺的,由于都是通路Nginx,然後再由nginx做轉發代理,是以域名是同一個,這樣cookie也是可以共享的,這裡有一個點需要注意一下,webaikn可能是多機部署,是以nginx在做轉發的時候需要設定ip_hash政策,目的就是保證使用者上一次請求通路的哪台伺服器,下一次還是通路那一台伺服器,不至于導緻session丢失的情況.   

SSO單點登入統一身份認證系統

點評:解決了多機部署單點登入失效的情況,但是還是需要伺服器端儲存使用者的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中存放的肯定是最簡單的一些使用者資訊)

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

SSO單點登入統一身份認證系統

來源:https://www.cnblogs.com/renchunpeng/p/11753921.html

SSO單點登入統一身份認證系統