SpringBoot3集成Oauth2——1(/oauth2/token方法的升級踩坑)

備注:本文適用于你在SpringBoot2.7以前集成過oauth2,并且項目已經正式投入使用的情況,否則,我建議你直接學習或者找資料學習最新的oauth2集成,就不要糾結于老版本的oauth2。

原因:Spring Security 5.x和Spring Security6.x,我個人認為,你可以理解為兩套不同的框架,他們僅僅只是名字差不多而已,升級難度在于,舊系統的登錄認證已經在使用了,尤其是已經介入很多子系統時,這時候需升級需要適配原來的認證,不然會導致子系統需要重新單點登錄。

Spring Security 5.x → 6.x:
棄用舊 API:spring-security-oauth2-autoconfigure 被移除,取而代之的是更模塊化的組件(如 spring-boot-starter-oauth2-client)。
新認證架構:基于 SecurityFilterChain 和 AuthenticationProvider 的聲明式配置取代了舊的 WebSecurityConfigurerAdapter。

本文部分內容參考:https://blog.csdn.net/gandilong 寫的SpringBoot+SpringSecurity OAuth2 認證服務搭建實戰 (二)

文章目錄

  • 1快速demo 授權服務器
    • 1.1依賴
    • 1.2AuthorizationServerConfig
    • 1.3SecurityConfig
    • 1.4驗證
  • 2老版本/oauth/token
  • 3問題:認證接口變了
  • 4新版本/oauth2/token
    • 4.1定位/oauth2/token

1快速demo 授權服務器

1.1依賴

springBoot版本

   <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.4</version><relativePath/> <!-- lookup parent from repository --></parent>
		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-oauth2-authorization-server</artifactId></dependency>

通過查看依賴,發現,SpringBoot3.4.4引用如下依賴

<dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-oauth2-authorization-server</artifactId><version>1.3.0</version><scope>compile</scope></dependency>

1.2AuthorizationServerConfig

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;@Configuration
@Import(OAuth2AuthorizationServerConfiguration.class)
public class AuthorizationServerConfig {OAuth2TokenEndpointFilter  OAuth2TokenEndpointFilter ;OAuth2AuthorizationServerConfigurer  OAuth2AuthorizationServerConfigurer;OAuth2ClientAuthenticationFilter  OAuth2ClientAuthenticationFilter ;@Beanpublic PasswordEncoder passwordEncoder() throws NoSuchAlgorithmException {return new BCryptPasswordEncoder(12,SecureRandom.getInstanceStrong());}/*** 提供登錄頁面用戶名密碼的認證* @return*/@Beanpublic UserDetailsService userDetailsService(PasswordEncoder passwdEncoder) {UserDetails user= User.builder().username("user")//.password(passwdEncoder.encode("123")) // 使用 {noop} 前綴表示密碼不會被編碼.password("{noop}123") // 使用 {noop} 前綴表示密碼不會被編碼.accountExpired(false).credentialsExpired(false).accountLocked(false).authorities("ROLE_USER") // 用戶的權限.build();return new InMemoryUserDetailsManager(user);}/*** 應用注冊倉庫* @return*/@Beanpublic RegisteredClientRepository registeredClientRepository(PasswordEncoder passwdEncoder) {RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString()).clientId("clientid").clientSecret(passwdEncoder.encode("client_secret"))如果是CLIENT_SECRET_POST才會用到.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC).clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST).clientAuthenticationMethod(ClientAuthenticationMethod.NONE).authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE).authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS).authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN).redirectUri("http://localhost:8080/login/oauth2/code/clientid").postLogoutRedirectUri("http://localhost:8080/").scope(OidcScopes.OPENID).scope(OidcScopes.PROFILE).build();return new InMemoryRegisteredClientRepository(oidcClient);}/*** 生成jwk,用在jwt編碼和jwt解碼器上* @return*/@Beanpublic JWKSource<SecurityContext> jwkSource() {KeyPair keyPair = generateRsaKey();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();RSAKey rsaKey = new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();JWKSet jwkSet = new JWKSet(rsaKey);return new ImmutableJWKSet<>(jwkSet);}/*** 生成RSA256非對稱的秘鑰對:公鑰和私鑰,其中公鑰會出布出去。* @return*/private static KeyPair generateRsaKey() {KeyPair keyPair;try {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);keyPair = keyPairGenerator.generateKeyPair();}catch (Exception ex) {throw new IllegalStateException(ex);}return keyPair;}/*** jwt 解碼器,給資源服務器用* @param jwkSource* @return*/@Beanpublic JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);}/*** jwt 編碼器,給授權服務器用* @param jwkSource* @return*/@Beanpublic JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {return new NimbusJwtEncoder(jwkSource);}/*** 默認授權服務器配置* @return*/@Beanpublic AuthorizationServerSettings authorizationServerSettings() {return AuthorizationServerSettings.builder().build();}
}

1.3SecurityConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;@Configuration
@EnableWebSecurity
public class SecurityConfig {@Bean@Order(1)public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)throws Exception {http.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated()).oauth2ResourceServer(resourceServer -> resourceServer.jwt(Customizer.withDefaults()));return http.build();}}

1.4驗證

需要注意,這里使用post + x-www-form-urlencoded來請求,這個是區別于老版本(大概應該是boot2.7以前)
在這里插入圖片描述
如果你在springBoot2.7以前用過oauth2,對于上述的方式肯定會很蒙蔽,接下來我們來說明為啥會這樣。

2老版本/oauth/token

如下為例,下面是我們一個老版本的oauth2的登錄認證接口,這里我用密碼模式來舉例

http://127.0.0.1:8080/oauth/token?client_id=client_hutao&client_secret=secret_hutao&username=hutao&password=123456&grant_type=password
我們使用postMan調用,如下所示
在這里插入圖片描述
兩者一對比就能發現,老版在url里面傳參數,新版在請求體x-www-form-urlencoded傳參數。
老版oauth2使用我們比較熟悉的Spring框架的接口開發方式來實現,如下代碼所示

@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)@RequestParam Map<String, String> parameters

因此我們想要去閱讀源碼或者調試信息時,只需要對org.springframework.security.oauth2.provider.endpoint.TokenEndpoint打debug打斷點就可以了,該代碼閱讀起來難度也比較小,很貼近我們比較常見的restful接口的開發。
在這里插入圖片描述

3問題:認證接口變了

我們先拋開我們怎么搭建授權服務器的問題,以及我現在為什么要從springBoot2升級到springBoot3,先解決一個問題,那就是,我們做授權服務器來實現單點登錄這些功能,為啥要這樣做?因為我們有很多系統都會調用這個單點登錄來實現登錄。也就是說,我們的這個登錄認證接口是被很系統正在使用的,現在如果直接就升級,會導致我們很多子系統要跟著改,這影響很大,因此,我們從springBoot2升級到springBoot3(沒有商量,必須升級)以后,oauth2也得跟著升級,我們得保證oauth2跟著升級以后,我們在新版本的oauth2下,得適配以前其他系統對接的接口。

4新版本/oauth2/token

通過上面的案例,我們發現接口地址變了,以前是/oauth/token,現在是/oauth2/token,并且
現在TokenEndpoint它不見了,不是說換個名字,是正兒八經的被刪除了,通過追蹤發現,/oauth2/token的工作原理機制和/oauth/token完全不一樣。

特性舊版 (Spring Security OAuth2)新版 (Spring Authorization Server)
依賴spring-security-oauth2(已廢棄)spring-boot-starter-oauth2-authorization-server
端點類TokenEndpoint(顯式 @FrameworkEndpoint)無集中式端點類,改為分散的 Filter + AuthenticationProvider OAuth2TokenEndpointFilter
請求方法支持 GET/POST /oauth/token僅支持 POST /oauth2/token
代碼入口直接由 TokenEndpoint 處理通過過濾器鏈和認證提供者協作處理

4.1定位/oauth2/token

如下所示,當我們請求這個接口時,實際上是下面這個OAuth2TokenEndpointFilter處理,而不是以前的那種,TokenEndpoint中的@RequestMapping(value = “/oauth/token”)處理
在這里插入圖片描述
如下所示,你就可以盡情的debug,查看請求參數或者報錯信息,來幫助你定位問題了
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904762.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904762.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904762.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

筆記本電腦實現網線內網 + Wi-Fi外網同時使用的配置方案

1、同時連接兩個網絡? 插入網線連接內網&#xff0c;確保內網IP地址正常獲取&#xff08;如10.143.88.x&#xff09;&#xff1b;連接Wi-Fi接入外網&#xff0c;確認可正常訪問互聯網&#xff08;如網關為192.168.8.1&#xff09;。 2、 記錄關鍵網絡參數? 內網網關&#…

從韋斯利?卡普洛看北斗星咨詢公司的技術咨詢引領之路

在科技與商業深度交融的時代&#xff0c;技術咨詢公司扮演著舉足輕重的角色&#xff0c;它們宛如連接技術創新與企業實際需求的橋梁&#xff0c;助力企業在復雜多變的市場環境中找準技術發展方向&#xff0c;實現可持續增長。《對話 CTO&#xff0c;駕馭高科技浪潮》的第 5 章聚…

首版次軟件測試的內容有哪些?首版次軟件質量影響因素是什么?

首版次軟件測試不僅是簡單的“找錯”&#xff0c;更是系統地驗證和評估軟件各項功能和性能指標是否符合設計標準。 一、首版次軟件測試常見的測試內容   1.功能測試&#xff1a;對照需求文檔&#xff0c;確認功能模塊是否按預期實現&#xff0c;用戶操作流程是否順暢。   …

從零開始的python學習(六)P86+P87+P88

本文章記錄觀看B站python教程學習筆記和實踐感悟&#xff0c;視頻鏈接&#xff1a;【花了2萬多買的Python教程全套&#xff0c;現在分享給大家&#xff0c;入門到精通(Python全棧開發教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS/?p6&share_sourcecopy_web&v…

從設計到開發,原型標注圖全流程標準化

一、原型標注圖是什么&#xff1f; 原型標注圖&#xff08;Annotated Prototype&#xff09;是設計原型&#xff08;Prototype&#xff09;的詳細說明書&#xff0c;通過圖文結合的方式&#xff0c;將設計稿中的視覺樣式、交互邏輯、適配規則等技術細節轉化為開發可理解的標準…

飛云分倉操盤副圖指標操作技術圖文分解

如上圖&#xff0c;副圖指標-飛云分倉操盤指標&#xff0c;指標三條線藍色“首峰線”&#xff0c;紅色“引力1”&#xff0c;青色“引力2”&#xff0c;多頭行情時“首峰線”和“引力1”之間顯示為紅色&#xff0c;“引力1”和“引力2”多頭是區間顏色顯示為紫色。 如上圖圖標信…

【LUT技術專題】ECLUT代碼解讀

目錄 原文概要 1. 訓練 2. 轉表 3. 測試 本文是對ECLUT技術的代碼解讀&#xff0c;原文解讀請看ECLUT。 原文概要 ECLUT通過EC模塊增大網絡感受野&#xff0c;提升超分效果&#xff0c;實現SRLUT的改進&#xff0c;主要是2個創新點&#xff1a; 提出了一個擴展卷積&…

動態規劃之背包問題:組合優化中的經典NP挑戰

背包問題概念&#xff1a; 背包問題是一種經典的組合優化的NP問題&#xff0c;在計算機科學、運籌學等領域有著廣泛的應用。 問題可以簡單的描述為&#xff1a; 假設有一個容量為C的背包和n個物品&#xff0c;每個物品i都有重量w[i]和價值v[i]。目標是選擇一些物品放入背包&…

vue3: pdf.js5.2.133 using typescript

npm install pdfjs-dist5.2.133 項目結構&#xff1a; <!--* creater: geovindu* since: 2025-05-09 21:56:20* LastAuthor: geovindu* lastTime: 2025-05-09 22:12:17* 文件相對于項目的路徑: \jsstudy\vuepdfpreview\comonents\pdfjs.vue* message: geovindu* IDE: vscod…

H2Database SQL 插入流程

H2Database SQL 插入流程 插入數據時會先進行 SQL 解析,然后找到插入表對應的 Primary Index 對應的 BTree,然后根據二分法定位到插入的葉子節點,將 key(主鍵) 和 value(Row) 插入到指定的葉子節點. 解析 SQL session 加鎖 創建 savepoint獲取or創建事務 設置 savepoint 執行…

虛擬機ubantu20.04系統橋接模式下無法ping通外網,但可以ping通本機的解決方案

1.出現的問題&#xff1a; 虛擬機ubantu20.04系統橋接模式下無法ping通外網,但可以ping通本機。 2.解決方案&#xff1a; 如果 DHCP 未分配 IP 地址&#xff0c;可以手動配置靜態 IP&#xff1a; 1.編輯網絡配置文件&#xff1a; sudo nano /etc/netplan/01-netcfg.yaml 修…

面對渠道競爭,品牌該如何應對?

無論是傳統零售渠道還是電商平臺的&#xff0c;渠道競爭仍舊是品牌維持和擴大影響力繞不開的一環。品牌想要保證自身的市場地位和盈利能力&#xff0c;就需要充分發揮各方面的優勢&#xff0c;來應對多變的市場環境。 一、改變產品定位 在存量市場上&#xff0c;消費者本身擁有…

SpringAI特性

一、SpringAI 顧問&#xff08;Advisors&#xff09; Spring AI 使用 Advisors機制來增強 AI 的能力&#xff0c;可以理解為一系列可插拔的攔截器&#xff0c;在調用 AI 前和調用 AI 后可以執行一些額外的操作&#xff0c;比如&#xff1a; 前置增強&#xff1a;調用 AI 前改…

101alpha_第6個

第6個alpha (-1 * correlation(open, volume, 10)) 這個就是看這兩個相似性。10天之內的 如果結果為正且數值較大&#xff0c;投資者可能會認為在開盤價上漲時成交量萎縮&#xff0c;市場上漲動力不足&#xff0c;可能是賣出信號&#xff1b;反之&#xff0c;開盤價下跌時成交…

【滲透測試】Web服務程序解析漏洞原理、利用方式、防范措施

文章目錄 Web服務程序解析漏洞原理、利用方式、防范措施一、原理**1. 定義與觸發條件****2. 攻擊鏈流程圖** 二、利用方式**1. 常見漏洞類型與利用手法**(1) IIS 5.x-6.x解析漏洞(2) Apache解析漏洞(3) Nginx解析漏洞(4) IIS 7.x解析漏洞(5) PHP CGI解析漏洞&#xff08;CVE-20…

SSL證書格式詳解:PEM、CER、DER、JKS、PKCS12等

引言 在網絡安全領域&#xff0c;SSL/TLS證書是保障互聯網通信安全的核心工具。它們通過加密連接&#xff0c;確保服務器與客戶端之間的數據隱私和完整性。然而&#xff0c;對于初學者來說&#xff0c;SSL證書的多種格式——PEM、CER、JKS、PKCS12、PFX等——常常令人困惑。每…

生信服務器如何安裝cellranger|生信服務器安裝軟件|單細胞測序軟件安裝

一.Why cellranger Cell Ranger 是由 10x Genomics 公司開發的一款用于處理其單細胞測序&#xff08;single-cell RNA-seq, scRNA-seq&#xff09;數據的軟件套件。它主要用于將原始測序數據&#xff08;fastq 文件&#xff09;轉換為可以用于下游分析的格式&#xff0c;比如基…

Redis 常見數據類型

Redis 常見數據類型 一、基本全局命令詳解與實操 1. KEYS 命令 功能&#xff1a;按模式匹配返回所有符合條件的鍵&#xff08;生產環境慎用&#xff0c;可能導致阻塞&#xff09;。 語法&#xff1a; KEYS pattern 模式規則&#xff1a; h?llo&#xff1a;匹配 hello, ha…

33號遠征隊 - 游玩鑒賞

風景很好畫質很好 , 圖片太大只能截圖一小部分 地編和特效 值得參考

使用JMETER中的JSON提取器實現接口關聯

一、JSON提取器介紹 JSON提取器是JMETER工具中用于從JSON響應中提取數據的重要組件&#xff0c;常常用于接口關聯場景中&#xff08;參數傳遞&#xff09;。 二、添加JSON提取器 舉例&#xff08;積分支付接口請求數據依賴于創建訂單接口響應的payOrderId&#xff09; 1.在…