天天看點

單點登入實作(spring session+redis完成session共享)

  

單點登入實作(spring session+redis完成session共享)

  我模拟了 sso的用戶端和sso的服務端, sso-core中主要是一些sso需要的過濾器和工具類,緩存和session共享的一些XML配置檔案,還有springmvc需要的一下jar包的管理。sso-cache中配置了redis緩存政策。

單點登入實作(spring session+redis完成session共享)

  簡單描述:

  使用者通路系統1的受保護資源,系統1發現使用者未登入,跳轉至sso認證中心,并将自己的位址作為參數

  sso認證中心發現使用者未登入,将使用者引導至登入頁面

  使用者輸入使用者名密碼送出登入申請

  sso認證中心校驗使用者資訊,建立使用者與sso認證中心之間的會話,稱為全局會話,同時建立授權令牌

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

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

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

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

  使用者通路系統2的受保護資源

  系統2發現使用者未登入,跳轉至sso認證中心,并将自己的位址作為參數

  sso認證中心發現使用者已登入,跳轉回系統2的位址,并附上令牌

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

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

  系統2使用該令牌建立與使用者的局部會話,傳回受保護資源

  1.SSOFilter.java(sso client filter實作)

單點登入實作(spring session+redis完成session共享)
單點登入實作(spring session+redis完成session共享)

View Code

  2.LoginController.java(sso server登入controller)

單點登入實作(spring session+redis完成session共享)
單點登入實作(spring session+redis完成session共享)

  3.ValidateController.java(sso server驗證token controller)

單點登入實作(spring session+redis完成session共享)
單點登入實作(spring session+redis完成session共享)

   4.在sso client工程中加上SSOFilter(web.xml部配置設定置)

單點登入實作(spring session+redis完成session共享)
單點登入實作(spring session+redis完成session共享)

  基本模型已經出來了,啟動sso-client 和 sso-server(本人都部署到了同一個tomcat下),試圖去驗證單點登入。測試的時候,從浏覽器中的cookie中檢視,可以看到 localhost域下有多個JSESSIONID。這也難怪, Tomcat中的每一個application都會建立自己的session會話。那接下來的事情就是解決 session 共享的問題,這樣我們就可以完成我們的單點登陸了。

  5.為每個工程的web.xml中增加spring session代理filter的配置

  6.在sso-core中加入 緩存和spring session的xml配置(cache-config.xml)

  這裡說一下為什麼有定義一個 cookieSerializer 這個bean。參看RedisHttpSessionConfiguration的源碼,發現它繼承了SpringHttpSessionConfiguration,繼續檢視源碼,發現SpringHttpSessionConfiguration中實作了我們配置的spring session代理filter,如下所示。

  檢視源碼,可以發現 SpringHttpSessionConfiguration使用的預設會話政策(httpSessionStrategy)是CookieHttpSessionStrategy。繼續檢視CookieHttpSessionStrategy的源碼,如建立session寫入cookie。

  cookieSerializer 預設是 DefaultCookieSerializer。檢視DefaultCookieSerializer 的 writeCookieValue方法如下。

  sessionCookie.setPath(getCookiePath(request));這塊有一個問題,看一下getCookiePath方法的實作,如下。

  如果要實作單點登入,就不要使用預設的 cookiePath 的值。是以,我定義了一個 cookieSerializer 的bean,并指定了 cookiePath 的值。 SpringHttpSessionConfiguration中如下方法可以自動裝配 我們配置的cookieSerializer,而不是使用預設的。

   7.在每個工程中的spring公共配置檔案中增加如下配置。

  8.後端之間rest請求傳遞 session ID。

  使用RestTemplate發送rest請求,發送之前複制request中的header資訊,保證session ID可以傳遞。

  9.最後,啟動工程,測試結果如下。

   

單點登入實作(spring session+redis完成session共享)

  http://study.hujunzheng.cn:8000/sso-client-user/  和  http://study.hujunzheng.cn:8000/sso-client-org/ 切換通路工程。