springboot webflux 過(guò)濾器中識(shí)別自定義注解校驗(yàn)Token

在WebFilter中識(shí)別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();

        // 獲取請(qǐng)求對(duì)應(yīng)的HandlerMethod
        Mono<HandlerMethod> handlerMethodMono = requestMappingHandlerMapping
                .getHandler(exchange).cast(HandlerMethod.class);

        return handlerMethodMono.zipWhen(handlerMethod -> {
            // 判斷Method是否含有對(duì)應(yīng)注解
            if (handlerMethod.hasMethodAnnotation(Token.class)) {

                MultiValueMap<String, String> params = req.getQueryParams();
                HttpHeaders headers = req.getHeaders();
                // 從參數(shù)中獲取token
                String token = params.getFirst("token");
                // 從header獲取token
                token = headers.getFirst("token");
                // TODO: 校驗(yàn)Token

                boolean valid = true;
                // 校驗(yàn)通過(guò),過(guò)濾器正常放行
                if (valid) return chain.filter(exchange);

            }

            // TODO: 校驗(yàn)不通過(guò),返回錯(cuò)誤信息
            res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
            byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
            return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));

        }).map(Tuple2::getT2);
    }

}

一些可能不用在意的點(diǎn):
1、Token.class改成自己對(duì)應(yīng)的注解

flag = handlerMethod.hasMethodAnnotation(Token.class);

2、設(shè)置狀態(tài)碼不是必須的,但這是個(gè)枚舉型,里面可能沒(méi)有一些你想要的奇怪值

res.setStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION);

3、自定義的返回內(nèi)容要轉(zhuǎn)成byte數(shù)組

byte[] bytes = "NON_AUTHORITATIVE_INFORMATION".getBytes();
return res.writeWith(Mono.just(res.bufferFactory().wrap(bytes)));

4、你需要的請(qǐng)求參數(shù)可以從這兒取

MultiValueMap<String, String> params = req.getQueryParams();
HttpHeaders headers = req.getHeaders();

5、Debug了幾遍,RequestMappingHandlerMapping的beanName是requestMappingHandlerMapping,他記錄了所有接口地址和對(duì)應(yīng)方法

@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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容