package com.doumee.config; import com.doumee.config.GatewayFilterProperties; import com.doumee.config.jwt.JwtTokenUtil; import com.doumee.core.utils.Constants; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import reactor.core.publisher.Mono; import javax.annotation.Resource; @Configuration public class CustomWebFilterConfig { @Autowired private RedisTemplate stringRedisTemplate; @Resource private GatewayFilterProperties notAuthUrlProperties; @Resource private JwtTokenUtil jwtTokenUtil; @Bean public WebFilter webFilter() { return (exchange, chain) -> { String url =exchange.getRequest().getURI().getPath(); if(!shouldSkip(url)){ String token = exchange.getRequest().getHeaders().getFirst(Constants.HEADER_USER_TOKEN); if (token == null || token.isEmpty()) { return unAuthorize(exchange); } String userInfo =(String) stringRedisTemplate.opsForValue().get(Constants.REDIS_TOKEN_KEY + token); if (StringUtils.isBlank(userInfo)) { return unAuthorize(exchange); } jwtTokenUtil.refreshTokenTime(token,userInfo); //把新的 exchange放回到过滤链 ServerHttpRequest request = exchange.getRequest().mutate().header(Constants.HEADER_USER_TOKEN, token).build(); ServerWebExchange newExchange = exchange.mutate().request(request).build(); return chain.filter(newExchange); } return chain.filter(exchange); }; } /** * 方法实现说明:不需要过滤的路径 *

* // * @param currentUrl 当前请求路径 */ private boolean shouldSkip(String currentUrl) { //如果没有登陆拦截目录,直接返回跳过校验 if(notAuthUrlProperties.getLoginFilterFolders() == null || notAuthUrlProperties.getLoginFilterFolders().size() ==0){ return true; } boolean isLoginFolder = false; for (String skipPath : notAuthUrlProperties.getLoginFilterFolders()) { if (skipPath.startsWith(currentUrl)) { isLoginFolder = true; } } if(!isLoginFolder){ //如果不在需要验证目录下,直接返回false,无需验证登录 return true; } //如果没有配置无需登录拦截的接口地址,直接返回false(需要验证) if(notAuthUrlProperties.getSkipLoginFilterUrls() == null || notAuthUrlProperties.getSkipLoginFilterUrls().size() ==0){ return false; } PathMatcher pathMatcher = new AntPathMatcher(); for (String skipPath : notAuthUrlProperties.getSkipLoginFilterUrls()) { if (pathMatcher.match(skipPath, currentUrl)) { return true; } } return false; } // 返回未登录的自定义错误 private Mono unAuthorize(ServerWebExchange exchange) { // 设置错误状态码为401 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); // 设置返回的信息为JSON类型 exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON); // 自定义错误信息 String errorMsg = "{\"error\": \"" + "用户未登录或登录超时,请重新登录" + "\"}"; // 将自定义错误响应写入响应体 return exchange.getResponse() .writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(errorMsg.getBytes()))); } }