用例是使用请求正文验证 JWT 中的数据。 JWT
sub
包含
{
"sub": "{\"data\": {\"street\": \"Street 1\", \"landmark\": \"TallestTower\"}}"
}
请求必须包含准确的数据。不符则禁止,否则请继续处理。
使用:
在调试期间,当它到达
ResourceRoutesHandler.create()
函数并尝试执行request.bodyToMono().flatMap()
时,它只是以HTTP 200退出。.flatMap()
中还有几个进一步的进程,但它们没有执行。有趣的是,工作区中没有 ServerResponse.ok()
可以使用 HTTP 200 产生这样的结果。
我的理解是这
ServerRequest.from(request).build()
导致了它。
有没有办法验证请求正文并发送相同的请求或在同一订阅内发送? 或者是否有其他方法可以在到达路由处理程序之前验证请求数据?
@Configuration
@RequiredArgsConstructor
public class ResourceRoutes {
final JwtHandlerFilterFunction jwtHandlerFilterFunction;
public RouterFunction<ServerResponse> createResource(ResourceRoutesHandler recourceRoutesHandler) {
return RouterFunction.route(
POST("/create").and(accept(MediaType.APPLICATION_JSON)),
recourceRoutesHandler::create
)
.filter(jwtHandlerFilterFunction);
}
}
@Component()
@RequiredArgsConstructor
public class JwtHandlerFilterFunction
implements HandlerFilterFunction<ServerResponse, ServerResponse> {
final ObjectMapper objectMapper;
@Override
public Mono<ServerResponse> filter(final ServerRequest request,
final HandlerFunction<ServerResponse> next) {
Headers headers = request.headers();
Optional<String> jwtToken = Optional.ofNullable(headers.firstHeader("Auth-Token"));
return jwtToken.map(_jwt -> jwtValidateService
.validateReactive(_jwt)
.flatMap(verifyPayload(request))
.flatMap(validMessage -> next.handle(
// clone here and pass on to next
// this is causing fail to execute request in route handler
ServerRequest.from(request)
.build()
))
.onErrorResume(throwable -> ServerResponse.status(HttpStatus.FORBIDDEN)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue("Authorization failed")
) // jwt validation failed
)
.orElse(next.handle(request)); // to next if header not present
}
private Function<String, Mono<String>> verifyPayload(final ServerRequest clientRequest) {
return subject -> clientRequest
.bodyToMono(String.class) // as the body already read how to pass on to next handler?
.flatMap(requestData -> Mono.fromCallable(() -> {
// for simplicity
if (!subject.equals(requestData)) {
throw new RuntimeException("Invalid subject data");
}
return "Valid";
}));
}
}
感谢您的宝贵时间
我认为在
HandlerFilterFunction
中依赖请求正文不是一个好主意。请注意,ServerRequest.from(...)
方法不会复制正文,原因类似:正文发布者通常只能订阅和使用一次。
不再进一步争论整个安排,我认为您在您的情况下可能有出路:因为您将整个正文视为
String
中的 verifyPayload
,您也许可以将两个 jwtToken flatMap
合并为一个通过修改 verifyPayload
方法,如下所示:
private Function<String, Mono<String>> verifyPayload(final ServerRequest clientRequest,
//added the HandlerFunction as a parameter
final HandlerFunction<ServerResponse> next) {
return subject -> clientRequest
.bodyToMono(String.class)
.flatMap(body -> {
// for simplicity
if (!subject.equals(body)) {
throw new RuntimeException("Invalid subject data");
}
//we have already read the full body, so we can "forward" it
return next.handle(ServerRequest.from(clientRequest).body(body).build());
}));
}