From 50a18d575097f039f19842025de596f3e7e73335 Mon Sep 17 00:00:00 2001 From: smallchill Date: Tue, 13 Aug 2019 14:03:03 +0800 Subject: [PATCH] =?UTF-8?q?:tada:=20=E4=BC=98=E5=8C=96=E9=89=B4=E6=9D=83?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E6=94=AF=E6=8C=81=E7=BD=91=E5=85=B3?= =?UTF-8?q?=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blade-gateway/pom.xml | 5 + .../config/RouterFunctionConfiguration.java | 7 +- .../{service => }/DynamicRouteService.java | 2 +- .../DynamicRouteServiceListener.java | 2 +- .../dynamic/{model => }/GatewayFilter.java | 2 +- .../dynamic/{model => }/GatewayPredicate.java | 2 +- .../dynamic/{model => }/GatewayRoute.java | 2 +- .../gateway/endpoint/RouteEndpoint.java | 6 +- .../gateway/filter/AuthFilter.java | 98 +++++++++++++++++++ ...stGlobalFilter.java => RequestFilter.java} | 2 +- .../handler/ErrorExceptionHandler.java | 19 +--- .../gateway/props/AuthProperties.java | 36 +++++++ .../gateway/provider/AuthProvider.java | 60 ++++++++++++ .../gateway/provider/ResponseProvider.java | 84 ++++++++++++++++ .../gateway/provider/SwaggerProvider.java | 1 - doc/nacos/blade.yaml | 12 +-- 16 files changed, 303 insertions(+), 37 deletions(-) rename blade-gateway/src/main/java/org/springblade/gateway/dynamic/{service => }/DynamicRouteService.java (98%) rename blade-gateway/src/main/java/org/springblade/gateway/dynamic/{service => }/DynamicRouteServiceListener.java (98%) rename blade-gateway/src/main/java/org/springblade/gateway/dynamic/{model => }/GatewayFilter.java (96%) rename blade-gateway/src/main/java/org/springblade/gateway/dynamic/{model => }/GatewayPredicate.java (96%) rename blade-gateway/src/main/java/org/springblade/gateway/dynamic/{model => }/GatewayRoute.java (96%) create mode 100644 blade-gateway/src/main/java/org/springblade/gateway/filter/AuthFilter.java rename blade-gateway/src/main/java/org/springblade/gateway/filter/{RequestGlobalFilter.java => RequestFilter.java} (96%) create mode 100644 blade-gateway/src/main/java/org/springblade/gateway/props/AuthProperties.java create mode 100644 blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java create mode 100644 blade-gateway/src/main/java/org/springblade/gateway/provider/ResponseProvider.java diff --git a/blade-gateway/pom.xml b/blade-gateway/pom.xml index 89dfd6a3..8760d1c6 100644 --- a/blade-gateway/pom.xml +++ b/blade-gateway/pom.xml @@ -42,6 +42,11 @@ + + org.springblade + blade-starter-jwt + ${bladex.project.version} + org.springframework.cloud diff --git a/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java b/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java index 470ebf44..1f926abb 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/config/RouterFunctionConfiguration.java @@ -19,6 +19,7 @@ package org.springblade.gateway.config; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springblade.gateway.handler.SwaggerResourceHandler; +import org.springblade.gateway.props.AuthProperties; import org.springblade.gateway.props.RouteProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -40,7 +41,7 @@ import reactor.core.publisher.Mono; @Slf4j @Configuration @AllArgsConstructor -@EnableConfigurationProperties(RouteProperties.class) +@EnableConfigurationProperties({RouteProperties.class, AuthProperties.class}) public class RouterFunctionConfiguration { private final SwaggerResourceHandler swaggerResourceHandler; @@ -48,12 +49,12 @@ public class RouterFunctionConfiguration { @Bean public RouterFunction routerFunction() { return RouterFunctions.route(RequestPredicates.GET("/swagger-resources") - .and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler); + .and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler); } /** - * 解决springboot2.0.5版本出现的 Only one connection receive subscriber allowed. + * 解决 Only one connection receive subscriber allowed. * 参考:https://github.com/spring-cloud/spring-cloud-gateway/issues/541 */ @Bean diff --git a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteService.java b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteService.java similarity index 98% rename from blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteService.java rename to blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteService.java index 363ada95..aed779ad 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteService.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteService.java @@ -14,7 +14,7 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ -package org.springblade.gateway.dynamic.service; +package org.springblade.gateway.dynamic; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.route.RouteDefinition; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteServiceListener.java b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteServiceListener.java similarity index 98% rename from blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteServiceListener.java rename to blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteServiceListener.java index 95af9cc6..e7996bc3 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/service/DynamicRouteServiceListener.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/DynamicRouteServiceListener.java @@ -14,7 +14,7 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ -package org.springblade.gateway.dynamic.service; +package org.springblade.gateway.dynamic; import com.alibaba.cloud.nacos.NacosConfigProperties; import com.alibaba.cloud.nacos.NacosDiscoveryProperties; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayFilter.java b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayFilter.java similarity index 96% rename from blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayFilter.java rename to blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayFilter.java index b224c683..a7c64ec8 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayFilter.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayFilter.java @@ -14,7 +14,7 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ -package org.springblade.gateway.dynamic.model; +package org.springblade.gateway.dynamic; import lombok.Data; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayPredicate.java b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayPredicate.java similarity index 96% rename from blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayPredicate.java rename to blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayPredicate.java index 0c53a293..1e8e4351 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayPredicate.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayPredicate.java @@ -14,7 +14,7 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ -package org.springblade.gateway.dynamic.model; +package org.springblade.gateway.dynamic; import lombok.Data; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayRoute.java b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayRoute.java similarity index 96% rename from blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayRoute.java rename to blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayRoute.java index a9b6ff61..c1260093 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/dynamic/model/GatewayRoute.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/dynamic/GatewayRoute.java @@ -14,7 +14,7 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ -package org.springblade.gateway.dynamic.model; +package org.springblade.gateway.dynamic; import lombok.Data; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/endpoint/RouteEndpoint.java b/blade-gateway/src/main/java/org/springblade/gateway/endpoint/RouteEndpoint.java index 4b49902b..4e811561 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/endpoint/RouteEndpoint.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/endpoint/RouteEndpoint.java @@ -17,9 +17,9 @@ package org.springblade.gateway.endpoint; import lombok.AllArgsConstructor; -import org.springblade.gateway.dynamic.model.GatewayPredicate; -import org.springblade.gateway.dynamic.model.GatewayRoute; -import org.springblade.gateway.dynamic.service.DynamicRouteService; +import org.springblade.gateway.dynamic.GatewayPredicate; +import org.springblade.gateway.dynamic.GatewayRoute; +import org.springblade.gateway.dynamic.DynamicRouteService; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionLocator; diff --git a/blade-gateway/src/main/java/org/springblade/gateway/filter/AuthFilter.java b/blade-gateway/src/main/java/org/springblade/gateway/filter/AuthFilter.java new file mode 100644 index 00000000..c9d4fed8 --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/filter/AuthFilter.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the dreamlu.net developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: Chill 庄骞 (smallchill@163.com) + */ +package org.springblade.gateway.filter; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.Claims; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springblade.core.jwt.JwtUtil; +import org.springblade.gateway.props.AuthProperties; +import org.springblade.gateway.provider.AuthProvider; +import org.springblade.gateway.provider.ResponseProvider; +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.nio.charset.StandardCharsets; + +/** + * 鉴权认证 + * + * @author Chill + */ +@Slf4j +@Component +@AllArgsConstructor +public class AuthFilter implements GlobalFilter, Ordered { + private AuthProperties authProperties; + private ObjectMapper objectMapper; + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + String path = exchange.getRequest().getURI().getPath(); + if (isSkip(path)) { + return chain.filter(exchange); + } + ServerHttpResponse resp = exchange.getResponse(); + String headerToken = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_HEADER); + String paramToken = exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_HEADER); + if (StringUtils.isAllBlank(headerToken, paramToken)) { + return unAuth(resp, "缺失令牌,鉴权失败"); + } + String auth = StringUtils.isBlank(headerToken) ? paramToken : headerToken; + String token = JwtUtil.getToken(auth); + Claims claims = JwtUtil.parseJWT(token); + if (claims == null) { + return unAuth(resp, "请求未授权"); + } + return chain.filter(exchange); + } + + private boolean isSkip(String path) { + return AuthProvider.getDefaultSkipUrl().stream().map(url -> url.replace(AuthProvider.TARGET, AuthProvider.REPLACEMENT)).anyMatch(path::startsWith) + || authProperties.getSkipUrl().stream().map(url -> url.replace(AuthProvider.TARGET, AuthProvider.REPLACEMENT)).anyMatch(path::startsWith); + } + + private Mono unAuth(ServerHttpResponse resp, String msg) { + resp.setStatusCode(HttpStatus.UNAUTHORIZED); + resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); + String result = ""; + try { + result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg)); + } catch (JsonProcessingException e) { + log.error(e.getMessage(), e); + } + DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8)); + return resp.writeWith(Flux.just(buffer)); + } + + @Override + public int getOrder() { + return -100; + } + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java b/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestFilter.java similarity index 96% rename from blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java rename to blade-gateway/src/main/java/org/springblade/gateway/filter/RequestFilter.java index b3af9d9f..b351716c 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestGlobalFilter.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/filter/RequestFilter.java @@ -25,7 +25,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.a * @author lengleng */ @Component -public class RequestGlobalFilter implements GlobalFilter, Ordered { +public class RequestFilter implements GlobalFilter, Ordered { /** * Process the Web request and (optionally) delegate to the next diff --git a/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java b/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java index 0baa2cbb..282ab0c7 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/handler/ErrorExceptionHandler.java @@ -16,6 +16,7 @@ */ package org.springblade.gateway.handler; +import org.springblade.gateway.provider.ResponseProvider; import org.springframework.boot.autoconfigure.web.ErrorProperties; import org.springframework.boot.autoconfigure.web.ResourceProperties; import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler; @@ -26,7 +27,6 @@ import org.springframework.http.HttpStatus; import org.springframework.web.reactive.function.server.*; import org.springframework.web.server.ResponseStatusException; -import java.util.HashMap; import java.util.Map; /** @@ -54,7 +54,7 @@ public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler { if (error instanceof ResponseStatusException) { code = ((ResponseStatusException) error).getStatus().value(); } - return response(code, this.buildMessage(request, error)); + return ResponseProvider.response(code, this.buildMessage(request, error)); } /** @@ -98,19 +98,4 @@ public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler { return message.toString(); } - /** - * 构建返回的JSON数据格式 - * - * @param status 状态码 - * @param errorMessage 异常信息 - * @return - */ - public static Map response(int status, String errorMessage) { - Map map = new HashMap<>(16); - map.put("code", status); - map.put("message", errorMessage); - map.put("data", null); - return map; - } - } diff --git a/blade-gateway/src/main/java/org/springblade/gateway/props/AuthProperties.java b/blade-gateway/src/main/java/org/springblade/gateway/props/AuthProperties.java new file mode 100644 index 00000000..c0908a76 --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/props/AuthProperties.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the dreamlu.net developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: Chill 庄骞 (smallchill@163.com) + */ +package org.springblade.gateway.props; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.ArrayList; +import java.util.List; + +/** + * 权限过滤 + * + * @author Chill + */ +@Data +@ConfigurationProperties("blade.secure") +public class AuthProperties { + + private final List skipUrl = new ArrayList<>(); + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java b/blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java new file mode 100644 index 00000000..5a7b53dc --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the dreamlu.net developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: Chill 庄骞 (smallchill@163.com) + */ +package org.springblade.gateway.provider; + +import java.util.ArrayList; +import java.util.List; + +/** + * 鉴权配置 + * + * @author Chill + */ +public class AuthProvider { + + public static String TARGET = "/**"; + public static String REPLACEMENT = ""; + public static String AUTH_HEADER = "Blade-Auth"; + private static List defaultSkipUrl = new ArrayList<>(); + + static { + defaultSkipUrl.add("/client/**"); + defaultSkipUrl.add("/oauth/token/**"); + defaultSkipUrl.add("/token/**"); + defaultSkipUrl.add("/actuator/health/**"); + defaultSkipUrl.add("/v2/api-docs/**"); + defaultSkipUrl.add("/v2/api-docs-ext/**"); + defaultSkipUrl.add("/auth/**"); + defaultSkipUrl.add("/log/**"); + defaultSkipUrl.add("/menu/routes"); + defaultSkipUrl.add("/menu/auth-routes"); + defaultSkipUrl.add("/menu/top-menu"); + defaultSkipUrl.add("/process/resource-view"); + defaultSkipUrl.add("/process/diagram-view"); + defaultSkipUrl.add("/manager/check-upload"); + defaultSkipUrl.add("/error/**"); + defaultSkipUrl.add("/assets/**"); + } + + /** + * 默认无需鉴权的API + */ + public static List getDefaultSkipUrl() { + return defaultSkipUrl; + } + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/provider/ResponseProvider.java b/blade-gateway/src/main/java/org/springblade/gateway/provider/ResponseProvider.java new file mode 100644 index 00000000..38f8efb6 --- /dev/null +++ b/blade-gateway/src/main/java/org/springblade/gateway/provider/ResponseProvider.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the dreamlu.net developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: Chill 庄骞 (smallchill@163.com) + */ +package org.springblade.gateway.provider; + +import java.util.HashMap; +import java.util.Map; + +/** + * 请求响应返回 + * + * @author Chill + */ +public class ResponseProvider { + + /** + * 成功 + * + * @param message 信息 + * @return + */ + public static Map success(String message) { + return response(200, message); + } + + /** + * 失败 + * + * @param message 信息 + * @return + */ + public static Map fail(String message) { + return response(400, message); + } + + /** + * 未授权 + * + * @param message 信息 + * @return + */ + public static Map unAuth(String message) { + return response(401, message); + } + + /** + * 服务器异常 + * + * @param message 信息 + * @return + */ + public static Map error(String message) { + return response(500, message); + } + + /** + * 构建返回的JSON数据格式 + * + * @param status 状态码 + * @param message 信息 + * @return + */ + public static Map response(int status, String message) { + Map map = new HashMap<>(16); + map.put("code", status); + map.put("message", message); + map.put("data", null); + return map; + } + +} diff --git a/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java b/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java index a6031b20..098b1286 100644 --- a/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java +++ b/blade-gateway/src/main/java/org/springblade/gateway/provider/SwaggerProvider.java @@ -14,7 +14,6 @@ * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ - package org.springblade.gateway.provider; import lombok.AllArgsConstructor; diff --git a/doc/nacos/blade.yaml b/doc/nacos/blade.yaml index 9c7ccbf6..fa79590a 100644 --- a/doc/nacos/blade.yaml +++ b/doc/nacos/blade.yaml @@ -69,14 +69,12 @@ management: #blade配置 blade: xss: - url: - exclude-patterns: - - /weixin - - /notice/submit + skip-url: + - /weixin + - /notice/submit secure: - url: - exclude-patterns: - - /test/** + skip-url: + - /test/** client: - client-id: sword path-patterns: