我目前正在使用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>
我的问题是我不知道如何正确编写这样的验证器。或者也许还有其他方法?
也许你可以像下面这样做
@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 提供的异步方法来处理响应。