特别说明: 注意这里验证码开关,指的是服务端不会校验请求的是否携带验证码及其正确性。 不是前端不显示验证码
nacos 配置
pigx-gateway-dev.yml

不校验验证码终端

ignore:
clients:

- 不校验验证码的终端client-id

webflux 生成验证码的 handler

import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzjt.gczjt.common.core.constant.CommonConstants;
import com.hzjt.gczjt.common.core.util.R;
import com.hzjt.gczjt.common.core.util.SpringContextHolder;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**

  • @author gczjt

  • @date 2020/5/19 验证码生成逻辑处理类
    */
    @Slf4j
    @Component
    @AllArgsConstructor
    public class ImageCodeCheckHandler implements HandlerFunction {

    private final ObjectMapper objectMapper;

    @Override
    @SneakyThrows
    public Mono handle(ServerRequest request) {

     CaptchaVO vo = new CaptchaVO();
     vo.setPointJson(request.queryParam("pointJson").get());
     vo.setToken(request.queryParam("token").get());
     vo.setCaptchaType(CommonConstants.IMAGE_CODE_TYPE);
    
     CaptchaService captchaService = SpringContextHolder.getBean(CaptchaService.class);
     ResponseModel responseModel = captchaService.check(vo);
    
     return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
             .body(BodyInserters.fromValue(objectMapper.writeValueAsString(R.ok(responseModel))));

    }

}

webflux 请求处理入口

public class RouterFunctionConfiguration {

private final ImageCodeCheckHandler imageCodeCheckHandler;

private final ImageCodeCreateHandler imageCodeCreateHandler;

private final SwaggerResourceHandler swaggerResourceHandler;

private final SwaggerSecurityHandler swaggerSecurityHandler;

private final SwaggerUiHandler swaggerUiHandler;

@Bean
public RouterFunction routerFunction() {
    return RouterFunctions
            .route(RequestPredicates.path("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                    imageCodeCreateHandler)

校验逻辑,通过 oauth2 终端的 client-id 来确定是否校验验证码

package com.hzjt.gczjt.gateway.filter;

import cn.hutool.core.util.StrUtil;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzjt.gczjt.common.core.constant.CacheConstants;
import com.hzjt.gczjt.common.core.constant.CommonConstants;
import com.hzjt.gczjt.common.core.constant.SecurityConstants;
import com.hzjt.gczjt.common.core.constant.enums.LoginTypeEnum;
import com.hzjt.gczjt.common.core.exception.ValidateCodeException;
import com.hzjt.gczjt.common.core.util.R;
import com.hzjt.gczjt.common.core.util.SpringContextHolder;
import com.hzjt.gczjt.common.core.util.WebUtils;
import com.hzjt.gczjt.gateway.config.FilterIgnorePropertiesConfig;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

/**

  • @author gczjt

  • @date 2020/5/19 登录逻辑验证码处理
    */
    @Slf4j
    @Component
    @AllArgsConstructor
    public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory {

    private final ObjectMapper objectMapper;

    private final RedisTemplate redisTemplate;

    private final FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;

    @Override
    public GatewayFilter apply(Object config) {

     return (exchange, chain) -> {
         ServerHttpRequest request = exchange.getRequest();
    
         // 不是登录请求,直接向下执行
         if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.OAUTH_TOKEN_URL,
                 SecurityConstants.SMS_TOKEN_URL, SecurityConstants.SOCIAL_TOKEN_URL)) {
             return chain.filter(exchange);
         }
    
         // 刷新token,直接向下执行
         String grantType = request.getQueryParams().getFirst("grant_type");
         if (StrUtil.equals(SecurityConstants.REFRESH_TOKEN, grantType)) {
             return chain.filter(exchange);
         }
    
         // 终端设置不校验, 直接向下执行
         try {
             String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
             String clientId = WebUtils.extractClientId(header).orElse(null);
             if (StrUtil.isNotBlank(clientId) && filterIgnorePropertiesConfig.getClients().contains(clientId)) {
                 return chain.filter(exchange);
             }
    
             // 如果是社交登录,判断是否包含SMS
             if (StrUtil.containsAnyIgnoreCase(request.getURI().getPath(), SecurityConstants.SOCIAL_TOKEN_URL)) {
                 String mobile = request.getQueryParams().getFirst("mobile");
                 if (StrUtil.containsAny(mobile, LoginTypeEnum.SMS.getType())) {
                     throw new ValidateCodeException("验证码不合法");
                 }
                 else {
                     return chain.filter(exchange);
                 }
             }
    
             // 校验验证码
             checkCode(request);
         }
         catch (Exception e) {
             ServerHttpResponse response = exchange.getResponse();
             response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
             response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED);
             try {
                 return response.writeWith(Mono.just(
                         response.bufferFactory().wrap(objectMapper.writeValueAsBytes(R.failed(e.getMessage())))));
             }
             catch (JsonProcessingException e1) {
                 log.error("对象输出异常", e1);
             }
         }
    
         return chain.filter(exchange);
     };

    }

文档更新时间: 2021-08-10 17:00   作者:admin