springboot webflux 过滤器中识别自定义注解校验
2021-03-24 本文已影响0人
itkkanae
在WebFilter中识别web接口上添加的自定义注解:
Controller的接口如下(@Token是自己建立的注解):
@Token
@GetMapping("/test")
public Mono<String> test() {
return Mono.just("success");
}
WebFilter代码:
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class TokenFilter implements WebFilter {
@Resource
private RequestMappingHandlerMapping requestMappingHandlerMapping;
private boolean flag;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpResponse res = exchange.getResponse();
ServerHttpRequest req = exchange.getRequest();
// 获取请求对应的HandlerMethod
Mono<HandlerMethod> handlerMethodMono = requestMappingHandlerMapping
.getHandler(exchange).cast(HandlerMethod.class);
return handlerMethodMono.zipWhen(handlerMethod -> {
// 判断Method是否含有对应注解
if (handlerMethod.hasMethodAnnotation(Token.class)) {
MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();
// 从参数中获取token
String token = params.getFirst("token");
// 从header获取token
token = headers.getFirst("token");
// TODO: 校验Token
boolean valid = true;
// 校验通过,过滤器正常放行
if (valid) return chain.filter(exchange);
}
// TODO: 校验不通过,返回错误信息
res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));
}).map(Tuple2::getT2);
}
}
一些可能不用在意的点:
1、Token.class改成自己对应的注解
flag = handlerMethod.hasMethodAnnotation(Token.class);
2、设置状态码不是必须的,但这是个枚举型,里面可能没有一些你想要的奇怪值
res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
3、自定义的返回内容要转成byte数组
byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));
4、你需要的请求参数可以从这儿取
MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();
5、Debug了几遍,RequestMappingHandlerMapping的beanName是requestMappingHandlerMapping,他记录了所有接口地址和对应方法
@Resource
private RequestMappingHandlerMapping requestMappingHandlerMapping;
6、springboot版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/>
</parent>