package com.scaffolding.sophia.gateway.filter; import cn.hutool.core.util.StrUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.scaffolding.sophia.gateway.exception.ValidateCodeException; 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.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.HashMap; import java.util.Map; /** * @author LHL * 验证码处理 */ @Slf4j @Component @AllArgsConstructor public class ValidateCodeGatewayFilter extends AbstractGatewayFilterFactory { private final ObjectMapper objectMapper; private final RedisTemplate redisTemplate; private final String OAUTH_TOKEN_URL = "/oauth/token"; private final String REFRESH_TOKEN = "refresh_token"; /** * 验证码前缀 */ private final String DEFAULT_CODE_KEY = "DEFAULT_CODE_KEY_"; @Override public GatewayFilter apply(Object config) { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); // 不是登录请求,直接向下执行 if (!StrUtil.containsAnyIgnoreCase(request.getURI().getPath() , OAUTH_TOKEN_URL)) { return chain.filter(exchange); } // 刷新token,直接向下执行 String grantType = request.getQueryParams().getFirst("grant_type"); if (StrUtil.equals(REFRESH_TOKEN, grantType)) { return chain.filter(exchange); } // 终端设置不校验, 直接向下执行 try { //校验验证码 checkCode(request); } catch (Exception e) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.PRECONDITION_REQUIRED); try { Map map= new HashMap<>(); map.put("code",-1); map.put("msg","失败"); return response.writeWith(Mono.just(response.bufferFactory() .wrap(objectMapper.writeValueAsBytes(map)))); } catch (JsonProcessingException e1) { log.error("对象输出异常", e1); } } return chain.filter(exchange); }; } /** * 检查code * * @param request */ @SneakyThrows private void checkCode(ServerHttpRequest request) { String code = request.getQueryParams().getFirst("code"); if (StrUtil.isBlank(code)) { throw new ValidateCodeException("验证码不能为空"); } String randomStr = request.getQueryParams().getFirst("randomStr"); if (StrUtil.isBlank(randomStr)) { randomStr = request.getQueryParams().getFirst("mobile"); } String key = DEFAULT_CODE_KEY + randomStr; if (!redisTemplate.hasKey(key)) { throw new ValidateCodeException("验证码不合法"); } Object codeObj = redisTemplate.opsForValue().get(key); if (codeObj == null) { throw new ValidateCodeException("验证码不合法"); } String saveCode = codeObj.toString(); if (StrUtil.isBlank(saveCode)) { redisTemplate.delete(key); throw new ValidateCodeException("验证码不合法"); } if (!StrUtil.equals(saveCode, code)) { redisTemplate.delete(key); throw new ValidateCodeException("验证码不合法"); } redisTemplate.delete(key); } }