Spring WebFlux中如何通过处理程序方法拦截请求

Nik*_*hXP 5 spring spring-mvc spring-webflux

我在Spring MVC中有以下拦截器,用于检查用户是否可以访问处理程序方法:

class AccessInterceptor : HandlerInterceptorAdapter() {

override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any?): Boolean {
    val auth: Auth =
        (if (method.getAnnotation(Auth::class.java) != null) {
            method.getAnnotation(Auth::class.java)
        } else {
            method.declaringClass.getAnnotation(Auth::class.java)
        }) ?: return true
    if (auth.value == AuthType.ALLOW) {
        return true
    }

    val user = getUserFromRequest(request) // checks request for auth token
    // and checking auth for out user in future.
    return renderError(403, response)
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我对方法进行注释,如下所示:

@GetMapping("/foo")
@Auth(AuthType.ALLOW)
fun doesntNeedAuth(...) { ... }

@GetMapping("/bar")
@Auth(AuthType.ADMIN)
fun adminMethod(...) { ... }
Run Code Online (Sandbox Code Playgroud)

如果用户使用了错误的令牌或没有权限,则会返回错误。
在Spring WebFlux中使用注释样式的控制器可以做到这一点吗?

Yue*_* Li 2

我的实现,不使用toFuture().get()它可能会阻塞。

@Component
@ConditionalOnWebApplication(type = Type.REACTIVE)
public class QueryParameterValidationFilter implements WebFilter {

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @NonNull
    @Override
    public Mono<Void> filter(@NonNull ServerWebExchange exchange, @NonNull WebFilterChain chain) {
        return handlerMapping.getHandler(exchange)
            .doOnNext(handler -> validateParameters(handler, exchange))
            .then(chain.filter(exchange));
    }

    private void validateParameters(Object handler, ServerWebExchange exchange) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Set<String> expectedQueryParams = Arrays.stream(handlerMethod.getMethodParameters())
                .map(param -> param.getParameterAnnotation(RequestParam.class))
                .filter(Objects::nonNull)
                .map(RequestParam::name)
                .collect(Collectors.toSet());
            Set<String> actualQueryParams = exchange.getRequest().getQueryParams().keySet();
            actualQueryParams.forEach(actual -> {
                if (!expectedQueryParams.contains(actual)) {
                    throw new InvalidParameterException(ERR_MSG, actual);
                }
            });
        }
    }
}
Run Code Online (Sandbox Code Playgroud)