java Spring Security 6 OAuth2自定义验证器

wkyowqbh  于 2023-04-28  发布在  Java
关注(0)|答案(1)|浏览(160)

在spring-boot 3上有一个java应用程序。0.5,它被配置为资源服务器,如下所示:
Maven依赖项:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
    </dependency>

安全配置:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
    
    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    private String issuerUri;
    
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().disable()
                .csrf().disable()
                .authorizeHttpRequests()
                .requestMatchers("/actuator/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .oauth2ResourceServer()
                .jwt();

        return http.build();
    }
    
    @Bean
    public JwtDecoder jwtDecoder() {
        NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri);

        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
        OAuth2TokenValidator<Jwt> withOperation = new OperationClaimValidator();

        jwtDecoder.setJwtValidator(
                new DelegatingOAuth2TokenValidator<>(withIssuer, withOperation)
        );

        return jwtDecoder;
    }
}

正如你所看到的,我定义了JwtDecoder bean来为JWT添加一个自定义验证器OperationClaimValidator,因为我想验证我的自定义jwt声明operation

import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
import org.springframework.security.oauth2.jwt.Jwt;

public class OperationClaimValidator implements OAuth2TokenValidator<Jwt> {

    private static final String CLAIM_OPERATION = "operation";
    
    
    @Override
    public OAuth2TokenValidatorResult validate(Jwt jwt) {
        if (jwt.getClaimAsString(CLAIM_OPERATION).equals("Value-from-HttpServletRequest")) { // problem here
            return OAuth2TokenValidatorResult.success();
        } else {
            return OAuth2TokenValidatorResult.failure(
                    new OAuth2Error("invalid_token", "The required operation is GET", null)
            );
        }
    }
}

问题是我想比较operation声明中的值和HttpServletRequest#getMethod中的值,但我不知道如何从OAuth2TokenValidator实现中访问HttpServletRequest

我可以使用OncePerRequestFilter以另一种方式验证这一说法:

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static final String CLAIM_OPERATION = "operation";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String requestMethod = request.getMethod();
        String operationClaimValue = getOperationClaimValue(request);

        if (!requestMethod.equals(operationClaimValue)) {
            response.sendError(HttpStatus.UNAUTHORIZED.value(),
                    "Operation claim in token does not match with http method used in request");
        } else {
            filterChain.doFilter(request, response);
        }
    }

    private String getOperationClaimValue(HttpServletRequest request) {
        Principal principal = request.getUserPrincipal();
        Jwt token = ((JwtAuthenticationToken) principal).getToken();
        return token.getClaimAsString(CLAIM_OPERATION);
    }
}

,但我想实现它实现OAuth2TokenValidator.有什么想法吗?先谢谢你。

3bygqnnd

3bygqnnd1#

您可以静态访问ServletRequest,如下所示:

public static Optional<HttpServletRequest> getRequest() {
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    if (requestAttributes instanceof ServletRequestAttributes attr) {
        return Optional.ofNullable(attr.getRequest());
    }
    return Optional.empty();
}

相关问题