Spring Security 与 Spring Boot 3 - 从安全上下文持有者获取 JWT 令牌

Jil*_*ill 5 spring-security spring-boot

迁移到 Spring Boot 3 后,

extends ResourceServerConfigurerAdapter is deprecrated.
Run Code Online (Sandbox Code Playgroud)

因此,无法使用覆盖的方法

   @Override
public void configure(ResourceServerSecurityConfigurer config) {
    config.tokenServices(tokenServices());
}
Run Code Online (Sandbox Code Playgroud)

我可以将其替换为

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeHttpRequests(auth->auth.
            requestMatchers(whitelistedEndPoints()).permitAll()
            .anyRequest()
            .anonymous())
            .httpBasic().disable();
    return http.build();
}
Run Code Online (Sandbox Code Playgroud)

我有一个现有代码可以从 OAuth 获取 jwt 令牌,如下所示

 public String getJwtTokenFromAuth() {
    OAuth2Authentication auth =(OAuth2Authentication) SecurityContextHolder.getContext().getAuthentication();
  
    OAuth2AuthenticationDetails oauth2AuthenticationDetails = (OAuth2AuthenticationDetails) auth.getDetails();
    return oauth2AuthenticationDetails.getTokenValue();
}
Run Code Online (Sandbox Code Playgroud)

然而,

OAuth2Authentication 和 OAuth2AuthenticationDetails 不可用

我如何用 Spring Boot 3 的新 Spring Security 模块替换此代码/功能。下面是 pom 依赖项,请建议我是否需要添加/删除任何依赖项?

  <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-oauth2-resource-server</artifactId>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

Val*_*udi 4

Spring Security OAuth2 已弃用并删除一段时间。替换是在 Spring Security 本身中构建的,并且要使用的依赖项正是您已经知道的:

所需的依赖项是:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
Run Code Online (Sandbox Code Playgroud)

为了获得资源服务器中的令牌值,您可以执行以下操作

class PrincipalIntrospector {
    
    public String token() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        JwtAuthenticationToken oauthToken = (JwtAuthenticationToken) authentication;
        return oauthToken.getToken().getTokenValue();
    }
    
}
Run Code Online (Sandbox Code Playgroud)

为了确保在您的主体中正确配置角色,您可以使用如下所示的内容:

@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> {
        List<String> authorities = jwt.getClaim("authorities");
        return authorities.stream().map(SimpleGrantedAuthority::new).collect(toList());
    });

    return jwtAuthenticationConverter;
}
Run Code Online (Sandbox Code Playgroud)

为了解码并让 spring 验证你的 jwt,你可以配置如下:

// used in case of public key
@Bean
public JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withPublicKey(this.key).build();
}
// used in case of the private key
@Bean
public JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withSecretKey(this.key).build();
}
Run Code Online (Sandbox Code Playgroud)

Spring Security 管道如下所示:

@Bean
public SecurityFilterChain filterChain(
        JwtDecoder  decoder,
        JwtAuthenticationConverter converter,
        HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.authorizeHttpRequests(auth->auth.
                    requestMatchers(whitelistedEndPoints()).permitAll()
                    .anyRequest()
                    .authenticated())
            .oauth2ResourceServer().jwt().decoder(decoder).jwtAuthenticationConverter(converter);
    return http.build();
}
Run Code Online (Sandbox Code Playgroud)