| package com.doumee.config; | 
|   | 
| 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.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<String,Object> 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); | 
|                 //把新的 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); | 
|         }; | 
|     } | 
|   | 
|     /** | 
|      * 方法实现说明:不需要过滤的路径 | 
|      * <p> | 
|      * //     * @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<Void> 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()))); | 
|     } | 
| } |