javascript
Spring Boot + OAuth2 统一认证SSO单点登录
需求:將項目從springSecurity驗證登錄改為統一認證sso登錄,將原數據庫中用戶賬號、密碼、郵箱信息遷移至統一認證端數據中,保留原客戶端項目的使用SpringSecurity進行權限角色管理部分
最終選擇spring boot +oauth2 ,用到 @EnableOAuth2Sso注解實現單點登錄,主要參考:
??Spring Boot+OAuth2,一個注解搞定單點登錄! - 江南一點雨 (javaboy.org)
本文記錄踩坑與學習與實戰記錄(未更完)
目錄
基礎知識學習
cas和sso(了解):
cas
通過cas實現單點登錄?
Spring Security
身份認證流程解析
自定義用戶密碼驗證
Sprint Security 用戶權限管理
做到一個用戶只能登錄一次
徹底理解 Cookie、Session、Token
Spring Security基于oauth2的sso單點登錄(最后使用的方式)
?開源框架XXL-SSO
實戰江南一點雨:
遇到的問題:
用戶權限管理時
auth端無法跳轉index
一.基礎知識學習
1.1 cas和sso(了解):
【單點登錄】什么是 SSO 與 CAS?_happydecai的博客-CSDN博客_cas和sso
sso是一種框架,cas是實現sso的一種方法,當然,還有其他的方法,例如cookie
1.1.1 cas
從結構上看,CAS 包含兩個部分: CAS Server 和 CAS Client。CAS Server 需要獨立部署,主要負責對用戶的認證工作;CAS Client 負責處理對客戶端受保護資源的訪問請求,需要登錄時,重定向到 CAS Server。下圖是 CAS 最
鏈接:單點登錄之CAS原理和實現_金玉良緣-CSDN博客_cas單點登錄實現原理
1.1.2 cas和oauth2 的區別
CAS的單點登錄和oauth2的最大區別 - 劍握在手 - 博客園
1.1.3. 通過cas實現單點登錄?
Spring Security 集成CAS實現單點登錄 - 阿貍哥哥 - 博客園
1.2 Spring Security
security 有認證和授權兩個功能 以session作為交互
1.2.1 身份認證流程解析
最簡單易懂的Spring Security 身份認證流程講解 - 曾俊杰的專欄 - 博客園 (cnblogs.com)
1.2.2 自定義用戶密碼驗證
關于密碼驗證源碼解讀寫于0706 · 語雀 (yuque.com)
重寫密碼驗證filter:
SpringSecurity的自定義用戶密碼驗證 - 洋洋哥 - 博客園 (cnblogs.com)
1.2.3 Sprint Security 用戶權限管理
1. 在config配置文件中配置:分為hasAuthority(String)、hasRole(String)、hasIpAddress(String)
(2條消息) Spring Security--角色權限判斷_我和井蓋都笑了博客-CSDN博客_springsecurity 判斷權限
protected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/api/**").hasAnyRole("ROLE_USER", "ROLE_ADMIN").antMatchers("/admin/**").hasRole("ROLE_ADMIN")// 如果發來的請求是指定的 IP 就允許訪問// 可以通過 request.getRemoteAddr()獲取 ip 地址。.antMatchers("/api/**").hasIpAddress("localhost").antMatchers("/api/**").hasAuthority("admin").and().logout().deleteCookies("JSESSIONID", oauthCookieName).invalidateHttpSession(true)// 這樣保證在客戶端logout的時候就在服務端logout.logoutSuccessUrl("http://{server.ip}/logout").and().authorizeRequests().anyRequest().authenticated();// 保證只有單方登錄,同時需要在auth端也配置這條,客戶端/logout了同時就會在統一認證端也執行logouthttp.sessionManagement().maximumSessions(1).expiredUrl("/logout");}2. 使用注解@PreAuthorize 進行管理權限
@PreAuthorize 注解,顧名思義是進入方法前的權限驗證,@PreAuthorize 聲明這個方法所需要的權限表達式,例如:@PreAuthorize("hasAuthority('sys:dept:delete')"),
@PreAuthorize 權限控制的原理 - 簡書 (jianshu.com)
3.?自定義注解進行權限管理
(2條消息) Java自定義注解實現權限管理_小識的博客-CSDN博客_注解實現權限管理
1.2.4 做到一個用戶只能登錄一次
1. 最大同時登錄為1,且配置session過期重定位地址,直接將原來登錄處踢出
當spring security檢查到session過期后,若未做任何配置,spring security會返回一個用戶不友好的頁面,因此我們通常需要設置一個地址,當spring security檢查到session過期后,將請求重定位到我們的地址上,設置代碼如下所示:
參考鏈接:
spring scurity session管理 - SegmentFault 思否
2. 當再次登錄時阻止其認證而不是強制踢出上一次登錄:
當一個用戶已經認證過了,在另外一個地方重新進行登錄認證,spring security可以阻止其再次登錄認證,從而保持原來的會話可用性;具體的代碼設置如下所示
http.sessionManager().maximumSession(1).maxSessionsPreventsLogin(true);參考鏈接:?
spring security 關于 http.sessionManagement().maximumSessions(1);的探究 - 岑惜 - 博客園 (cnblogs.com)
1.2.5 ?Cookie、Session、Token
1. 三者的關系
springbsecurity 登錄token驗證過濾器_徹底理解 Cookie、Session、Token_weixin_39693662的博客-CSDN博客
2. springsecurity session詳解:
參考:
Spring Security 控制Session詳解 - 簡書 (jianshu.com)
3. springSecurity 修改session中的信息
遇到場景 : 前端通過session獲取當前用戶信息,當前用戶信息在前端頁面發生了改變時(比如用戶update了自己的email屬性);可能數據庫里面已經update了,而程序沒有重啟或者用戶沒有重新登陸,則session中的值是不會發生改變的,即驗證的用戶信息也是不變的,前端顯示也并不會更新
SpringSecurity-日常踩坑,修改session中的用戶信息。 - EalenXie - 博客園 (cnblogs.com)
4. 根據session獲取用戶名
SpringSecurity-日常踩坑,修改session中的用戶信息。 - EalenXie - 博客園 (cnblogs.com)
1.3 Spring Security基于oauth2的sso單點登錄(最后使用的方式)
1. oauth2 主要目的是為了第三方登錄(例如微信授權), 提供以token作為訪問權限
參考:Spring Security基于Oauth2的SSO單點登錄怎樣做? - 程序員大本營
2. 當客戶端用security時:(2條消息) 基于Spring Security + OAuth2 的SSO單點登錄(客戶端)_Janche的博客-CSDN博客_oauth2 客戶端登錄
3.? @EnableOAuth2Sso注解實現單點登錄(在客戶端使用,客戶端用的是security驗證登錄)
(最終參考的方案)?
?Spring Boot+OAuth2,一個注解搞定單點登錄! - 江南一點雨 (javaboy.org)
auth端連接數據庫驗證用戶賬號和密碼需要配置datasource config需要配置
客戶端有單獨的權限管理,在security中配置,詳見"Sprint Security 用戶權限管理"
4. 注冊
spring-security-oauth2(二十二) 重構注冊邏輯_codeing-tiger-CSDN博客_oauth2 注冊
1.4 開源框架XXL-SSO
分布式單點登錄框架XXL-SSO - 許雪里 - 博客園
實現時遇到的問題:
做了很多嘗試把xxl-sso框架和springSecurity框架集成,但客戶端無法獲取用戶信息,無法實現原因:統一驗證那邊驗證登錄成功了,兩邊的session統一,但是客戶端項目的security驗證沒有通過,而我們需要它的username password攔截器驗證通過,才能獲得我們所需要的principal
二. 實戰:
參考項目地址:
https://github.com/lenve/oauth2-samples
clone項目后分別打開oauth2-sso/auth-server(認證端)、oauth2-sso/client1(客戶端1)、oauth2-sso/client2(客戶端2),開啟后可以實現統一認證登錄
接下來進行一些拓展:
2.1 客戶端登錄成功后跳轉index頁面
傳送門:
SpringBoot 登陸后跳轉到index頁面_aqing617的博客-CSDN博客
2.2 客戶端登出
客戶端的登出添加配置
http.logout() // .logoutUrl("/logout") // .deleteCookies("s1","JSESSIONID")// 在登出后,是否要清空當前session // .invalidateHttpSession(true)// 服務端登出.logoutSuccessUrl("http://localhost:1111/logout");認證端添加的配置:
http.logout();2.3 一個用戶只允許登錄一次?
需求:每個用戶在瀏覽器a登錄后,在瀏覽器b再次登錄,此時要求瀏覽器a 該用戶被踢出
在認證端和客戶端都添加配置
http.sessionManagement().maximumSessions(1).expiredUrl("/logout");2.4 認證端連接數據庫驗證用戶信息
原項目中,用戶信息是存在與程序內存中的,現添加配置,使得用戶信息存儲于數據庫中
1. securityConfig中替換
@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(userAuthenticationProvider).userDetailsService(userService).passwordEncoder(passwordEncoder);}2. 添加datasourceConfig,連接數據庫????????
通過添加import com.mysql.jdbc.Driver;自動在pom文件中添加依賴
搭建單點登錄服務器,新建數據庫用戶表用于用戶驗證
3. 注入bean
4. 定義user類,實現UserDetails接口
5.定義UseDAO
6. 定義UserService實現UserDetailService接口
7.添加認證處理類,即1.中所用的
8. application.properties添加配置,連接數據庫
2.5 新增user-center客戶端,用于展示引導鏈接到各個客戶端
首先在認證端新增接口,登錄成功后跳轉用戶中心客戶端
@GetMapping("/")public void redirect2UserCenter(HttpServletRequest req, HttpServletResponse resp) throws IOException {resp.sendRedirect("http://localhost:1112");}(未完待續)?
2.6 添加統一認證端的注冊邏輯?
在認證端新增注冊接口,調用后轉發調用客戶端接口,在認證端數據庫和客戶端數據庫都添加用戶信息
(未完待續)
2.7 客戶端權限管理
(未完待續)?
遇到的問題:
(未完待續)
用戶權限管理時
嘗試了多種方法解決用戶權限管理,用security自己的配置(獲取不到aizoo數據庫中的權限信息,只能獲取統一身份認證的),@PreAuthorize(同樣的問題),自己寫了攔截器和自定義注解攔截無果(攔截順序的問題,無法跳轉到統一身份認證)
auth端無法跳轉index,無法直接訪問任何接口
試圖解決統一認證服務器登錄之后無法跳轉index的bug,嘗試了后臺控制跳轉,報401錯誤(沒有權限
總結
以上是生活随笔為你收集整理的Spring Boot + OAuth2 统一认证SSO单点登录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring mvc学习(15)Refe
- 下一篇: gradle idea java ssm