最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Security?Oauth2整合JWT的詳細步驟和核心配置

 更新時間:2025年11月01日 11:38:08   作者:心態(tài)特好  
這篇文章主要介紹了Spring?Security?Oauth2整合JWT的詳細步驟和核心配置,包括依賴引入、JWT工具類、OAuth2和資源服務器配置以及SpringSecurity配置,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

先說步驟:

在 Spring Security 中整合 OAuth2 與 JWT,可實現(xiàn)基于令牌的認證授權機制,適合分布式系統(tǒng)場景。以下是詳細的整合步驟和核心配置:

1. 依賴引入

pom.xml中添加核心依賴(以 Spring Boot 為例):

<!-- Spring Security OAuth2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.3.8.RELEASE</version>
</dependency>

<!-- JWT支持 -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

<!-- Spring Web(用于測試接口) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2. 核心配置

2.1 JWT 工具類

用于生成、解析 JWT 令牌:

@Component
public class JwtTokenUtil {
    // 密鑰(實際項目中需加密存儲)
    private static final String SECRET = "your-secret-key";
    // 過期時間(7天)
    private static final long EXPIRATION = 604800000L;

    // 生成JWT令牌
    public String generateToken(String username) {
        Date now = new Date();
        Date expirationDate = new Date(now.getTime() + EXPIRATION);

        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(now)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    // 從令牌中獲取用戶名
    public String getUsernameFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    // 驗證令牌有效性
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

2.2 OAuth2 配置(授權服務器)

配置授權服務器,指定 JWT 作為令牌格式:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    // 配置客戶端信息(如客戶端ID、密鑰、授權類型等)
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client-id") // 客戶端ID
                .secret(passwordEncoder().encode("client-secret")) // 客戶端密鑰
                .authorizedGrantTypes("password", "refresh_token") // 支持的授權類型
                .scopes("read", "write") // 權限范圍
                .accessTokenValiditySeconds(3600) // 訪問令牌過期時間
                .refreshTokenValiditySeconds(86400); // 刷新令牌過期時間
    }

    // 配置令牌存儲(使用JWT)
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter() {
            @Override
            protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                // 自定義JWT載荷(可選)
                Map<String, Object> claims = new HashMap<>(accessToken.getAdditionalInformation());
                claims.put("username", authentication.getName());
                claims.put("authorities", authentication.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority)
                        .collect(Collectors.toList()));
                DefaultOAuth2AccessToken customToken = new DefaultOAuth2AccessToken(accessToken);
                customToken.setAdditionalInformation(claims);
                return super.encode(customToken, authentication);
            }
        };
        converter.setSigningKey(jwtTokenUtil.SECRET); // 設置簽名密鑰
        return converter;
    }

    // 配置令牌服務
    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService());
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore());
        services.setAccessTokenValiditySeconds(3600);
        services.setRefreshTokenValiditySeconds(86400);
        return services;
    }

    // JWT令牌存儲
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

2.3 資源服務器配置

配置受保護的資源,驗證 JWT 令牌:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    // 資源ID(需與授權服務器配置一致)
    private static final String RESOURCE_ID = "resource-id";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                .resourceId(RESOURCE_ID)
                .tokenStore(tokenStore()); // 使用JWT令牌存儲
    }

    // 配置資源訪問規(guī)則
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/public/**").permitAll() // 公開接口
                .antMatchers("/api/**").authenticated() // 需認證的接口
                .antMatchers("/admin/**").hasRole("ADMIN"); // 需ADMIN角色
    }

    @Bean
    public TokenStore tokenStore() {
        // 配置JWT驗證
        return new JwtTokenStore(new JwtAccessTokenConverter() {{
            setSigningKey(jwtTokenUtil.SECRET);
        }});
    }
}

2.4 Spring Security 配置

配置用戶認證信息和密碼加密:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        // 內(nèi)存用戶(實際項目中替換為數(shù)據(jù)庫查詢)
        UserDetails user = User.withUsername("user")
                .password(passwordEncoder().encode("123456"))
                .roles("USER")
                .build();
        UserDetails admin = User.withUsername("admin")
                .password(passwordEncoder().encode("123456"))
                .roles("ADMIN")
                .build();
        return new InMemoryUserDetailsManager(user, admin);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

3. 測試接口

編寫測試接口驗證效果:

@RestController
public class TestController {

    // 公開接口
    @GetMapping("/public/hello")
    public String publicHello() {
        return "Public Hello!";
    }

    // 需認證的接口
    @GetMapping("/api/hello")
    public String apiHello(Authentication authentication) {
        return "API Hello, " + authentication.getName() + "!";
    }

    // 需ADMIN角色的接口
    @GetMapping("/admin/hello")
    public String adminHello(Authentication authentication) {
        return "Admin Hello, " + authentication.getName() + "!";
    }
}

4. 測試流程

4.1 獲取令牌

通過password模式請求授權服務器的令牌端點:

POST http://localhost:8080/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic Y2xpZW50LWlkOmNsaWVudC1zZWNyZXQ=  # client-id:client-secret的Base64編碼

grant_type=password&username=user&password=123456

返回結果(JWT 格式的 access_token):

{
  "access_token": "eyJhbGciOiJIUzUxMiJ9...",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJIUzUxMiJ9...",
  "expires_in": 3599,
  "scope": "read write"
}

4.2 訪問受保護資源

使用獲取的access_token訪問接口:

GET http://localhost:8080/api/hello
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9...

返回:API Hello, user!

關鍵注意事項

  1. 密鑰安全:JWT 簽名密鑰需妥善保管,避免硬編碼(可通過配置中心或環(huán)境變量注入)。
  2. 令牌過期:合理設置access_tokenrefresh_token的過期時間,平衡安全性和用戶體驗。
  3. 自定義載荷:可在 JWT 中添加用戶角色、權限等信息,減少資源服務器查詢數(shù)據(jù)庫的次數(shù)。
  4. HTTPS:生產(chǎn)環(huán)境必須使用 HTTPS 傳輸令牌,防止中間人攻擊。

通過以上配置,即可實現(xiàn) Spring Security OAuth2 與 JWT 的整合,支持基于令牌的認證授權。

在來講幾個簡單的概念:

JWT 令牌包含了用戶信息(或其他數(shù)據(jù)),并通過數(shù)字簽名來保證這些信息的完整性和真實性。

具體來說,JWT 令牌由三部分組成(用 . 分隔):

  1. 頭部(Header):說明簽名算法(比如 HMAC、RSA 等)。
  2. 載荷(Payload):存放實際要傳遞的信息(比如用戶 ID、角色、過期時間等,這些就是 “用戶信息”)。
  3. 簽名(Signature):用頭部指定的算法,結合服務器的密鑰(或私鑰),對 “頭部 + 載荷” 進行加密生成的數(shù)字簽名。

所以,JWT 不只是數(shù)字簽名,而是 “信息 + 簽名” 的組合體。簽名的作用是:

  • 證明載荷里的信息沒被篡改(因為篡改后簽名會失效);
  • 證明信息確實來自可信的服務器(因為只有服務器有密鑰能生成正確的簽名)。

簡單講,JWT 就像一封 “帶防偽簽名的信”:信里寫了內(nèi)容(用戶信息),信封上的簽名(數(shù)字簽名)保證信沒被拆過、沒被改,且確實是發(fā)件人(服務器)發(fā)的。

JWT可以使用HMAC算法或使用RSA的公鑰/私鑰對來簽名,防止被篡改。 官網(wǎng):https://jwt.io/
 JWT 令牌的優(yōu)點:
jwt 基于json,非常方便解析。
可以在令牌中自定義豐富的內(nèi)容,易擴展。
通過非對稱加密算法及數(shù)字簽名技術,JWT防止篡改,安全性高。
資源服務使用JWT可不依賴認證服務即可完成授權。
缺點:
JWT 令牌較長,占存儲空間比較大

總結 

到此這篇關于Spring Security Oauth2整合JWT的詳細步驟和核心配置的文章就介紹到這了,更多相關Spring Security Oauth2整合JWT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解Java9新特性中的模塊化與反射機制

    詳解Java9新特性中的模塊化與反射機制

    Java9中的一個重大變化就是引入了模塊化系統(tǒng),這個系統(tǒng)使得Java應用程序的構建、發(fā)布和部署更加具有可控性和可重用性,與此同時,Java9還改進了反射機制,讓它與模塊化系統(tǒng)更好地配合,本文通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2023-06-06
  • 如何用Java來進行文件切割和簡單的內(nèi)容過濾的實現(xiàn)

    如何用Java來進行文件切割和簡單的內(nèi)容過濾的實現(xiàn)

    這篇文章主要介紹了如何用Java來進行文件切割和簡單的內(nèi)容過濾的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-01-01
  • JAVA自定義注解使用指南

    JAVA自定義注解使用指南

    注解是一種特殊的接口,用于為Java代碼提供元數(shù)據(jù),它們不會直接影響代碼的執(zhí)行,但可以被編譯器、開發(fā)工具或運行時環(huán)境讀取和使用,本文給大家介紹JAVA自定義注解的相關知識,感興趣的朋友一起看看吧
    2025-11-11
  • Java object類及正則表達式原理解析

    Java object類及正則表達式原理解析

    這篇文章主要介紹了Java object類及正則表達式原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • scala 隱式轉換與隱式參數(shù)的使用方法

    scala 隱式轉換與隱式參數(shù)的使用方法

    這篇文章主要介紹了scala 隱式轉換與隱式參數(shù)的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • spring @Scheduled注解的使用誤區(qū)及解決

    spring @Scheduled注解的使用誤區(qū)及解決

    這篇文章主要介紹了spring @Scheduled注解的使用誤區(qū)及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • JAVA8 lambda表達式權威教程

    JAVA8 lambda表達式權威教程

    本文主要給大家講解Java8中最重要的一個特征之一lambda表達式,本文通過實例圖文解說給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友跟隨小編一起學習下吧
    2021-05-05
  • 詳解如何在Java中調(diào)用Python程序

    詳解如何在Java中調(diào)用Python程序

    今天給大家?guī)淼氖顷P于Java中調(diào)用Python程序的相關知識,文章有非常詳細的代碼示例,需要的朋友可以參考下
    2021-06-06
  • Spring?AOP的注解實現(xiàn)方式實例詳解

    Spring?AOP的注解實現(xiàn)方式實例詳解

    AOP是一種對某一類事情集中處理的思想,本文給大家介紹Spring?AOP的注解實現(xiàn)方式實例詳解,感興趣的朋友一起看看吧
    2025-04-04
  • 基于java.lang.IllegalArgumentException異常報錯問題及解決

    基于java.lang.IllegalArgumentException異常報錯問題及解決

    這篇文章主要介紹了基于java.lang.IllegalArgumentException異常報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論

荆门市| 崇礼县| 广州市| 平江县| 镇远县| 抚顺市| 夏河县| 德令哈市| 乐陵市| 洛阳市| 新余市| 梁山县| 来凤县| 嵊泗县| 澄城县| 新兴县| 含山县| 建湖县| 永嘉县| 海兴县| 乐业县| 江北区| 阿尔山市| 弥渡县| 阿克苏市| 贵港市| 东城区| 柘荣县| 慈溪市| 体育| 常宁市| 长治市| 宜昌市| 普兰县| 宾阳县| 河西区| 兰州市| 泊头市| 浦城县| 新余市| 肥西县|