在线OAuth2TokenValidator + Spring Security + Spring WebFlux + WebClient

问题描述 投票:0回答:1

我目前正在使用Spring Webflux和Spring Security(Spring Boot 3.1.4)开发一个应用程序以确保安全性。为了实现这一目标,我利用了 Spring Boot Starter OAuth2 资源服务器依赖项。在 JWT 令牌的验证过程中,我需要对身份提供者 (IDP) 进行 HTTP 查询验证。我已经创建了一个

NimbusReactiveJwtDecoder
,现在打算设置我的自定义验证器。这就需要实现
OAuth2TokenValidator<Jwt>
接口。

考虑使用反应式堆栈,我正在使用 WebClient。但是,

OAuth2TokenValidator<Jwt>
中的 validate 方法返回
OAuth2TokenValidatorResult
而不是
Mono<OAuth2TokenValidatorResult>
。这使得直接返回
webclient.get().uri().retrieve()
的结果变得具有挑战性。此外,在响应式上下文中,无法使用
block()
blockOptional()
blockFirst()
blockLast()
等方法。

我的实现看起来像这样:

@Override
public OAuth2TokenValidatorResult validate(Jwt token) {
    return this.webClient
        .get()
        .uri(tokenValidationUri, token.getTokenValue())
        .retrieve()
        .toBodilessEntity()
        .map(ResponseEntity::getStatusCode)
        .map(statusCode -> {
            if (statusCode.is2xxSuccessful()) {
                return success();
            }
            return failure(createOAuth2Error());
        }).onErrorResume(throwable -> Mono.just(failure(createOAuth2Error())));
}

依赖关系:

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

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

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

我的问题是我不知道如何正确编写这样的验证器。或者也许还有其他方法?

spring-security jwt spring-webflux spring-security-oauth2
1个回答
0
投票

也许你可以像下面这样做

@Override
public OAuth2TokenValidatorResult validate(Jwt token) {
     CompletableFuture<OAuth2TokenValidatorResult> futureResult = new CompletableFuture<>();
        Schedulers.boundedElastic().schedule(() -> {
            try {
                OAuth2TokenValidatorResult result = validate0(token).block();
                futureResult.complete(result);
            } catch (Exception e) {
                futureResult.completeExceptionally(e);
            }
        });
        try {
            return futureResult.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
}



private OAuth2TokenValidatorResult validate0(Jwt token) {
    return this.webClient
        .get()
        .uri(tokenValidationUri, token.getTokenValue())
        .retrieve()
        .toBodilessEntity()
        .map(ResponseEntity::getStatusCode)
        .map(statusCode -> {
            if (statusCode.is2xxSuccessful()) {
                return success();
            }
            return failure(createOAuth2Error());
        }).onErrorResume(throwable -> Mono.just(failure(createOAuth2Error())));
}

在WebFlux中,不支持block()等阻塞操作,因为它会阻塞Reactor线程,破坏异步非阻塞原则。相反,您应该使用 Reactor 提供的异步方法来处理响应。

© www.soinside.com 2019 - 2024. All rights reserved.