Browse Source

first commit

felixyin 7 months ago
commit
a7314ebd1d

+ 19 - 0
.gitignore

@@ -0,0 +1,19 @@
+# Created by .ignore support plugin (hsz.mobi)
+### Example user template template
+### Example user template
+
+# IntelliJ project files
+.idea
+*.iml
+out
+gen
+target
+*.class
+
+*.log
+.settings
+.project
+logs
+job
+
+templates

+ 7 - 0
Dockerfile

@@ -0,0 +1,7 @@
+FROM openjdk:11-jdk
+LABEL maintainer="研究院研发组 <research-maint@itcast.cn>"
+RUN echo "Asia/Shanghai" > /etc/timezone
+ARG PACKAGE_PATH=./target/jzo2o-gateway.jar
+
+ADD ${PACKAGE_PATH:-./} app.jar
+ENTRYPOINT ["sh","-c","java  -jar $JAVA_OPTS app.jar"]

+ 11 - 0
jzo2o-gateway-startup.bat

@@ -0,0 +1,11 @@
+@echo off
+chcp 65001
+title jzo2o-gateway
+echo.
+echo [信息] 打包网关工程。
+echo.
+call  mvn  package -DskipTests=true
+echo.
+echo [信息] 启动网关工程。
+echo.
+java -Dfile.encoding=utf-8 -Xmx128m -jar target/jzo2o-gateway.jar

+ 79 - 0
pom.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>jzo2o-parent</artifactId>
+        <groupId>com.jzo2o</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>com.jzo2o</groupId>
+    <artifactId>jzo2o-gateway</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.jzo2o</groupId>
+            <artifactId>jzo2o-common</artifactId>
+        </dependency>
+        <!--网关-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <!--loadbalancer-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+        <!--开启bootstrap文件读取-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+
+        <!-- spring cloud gateway server中使用到了,需要引入该依赖,否则会报错 -->
+        <dependency>
+            <groupId>org.hibernate.validator</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>6.1.5.Final</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build-info</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <mainClass>com.jzo2o.gateway.GatewayApplication</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 17 - 0
src/main/java/com/jzo2o/gateway/GatewayApplication.java

@@ -0,0 +1,17 @@
+package com.jzo2o.gateway;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+@Slf4j
+public class GatewayApplication {
+
+    public static void main(String[] args) {
+        new SpringApplicationBuilder(GatewayApplication.class)
+                .build(args)
+                .run(args);
+        log.info("家政o2o-网关服务启动");
+    }
+}

+ 34 - 0
src/main/java/com/jzo2o/gateway/config/JwtToolConfiguration.java

@@ -0,0 +1,34 @@
+package com.jzo2o.gateway.config;
+
+import cn.hutool.extra.spring.SpringUtil;
+import com.jzo2o.common.utils.JwtTool;
+import com.jzo2o.gateway.properties.ApplicationProperties;
+import com.jzo2o.gateway.constants.UserConstants;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * 生成多个token解析器
+ */
+@Configuration
+public class JwtToolConfiguration {
+
+    @Resource
+    private ApplicationProperties applicationProperties;
+
+    /**
+     * 初始化JwtTool
+     */
+    @PostConstruct
+    public void initJwtTools() {
+        for (Map.Entry<String, String> entry : applicationProperties.getTokenKey().entrySet()) {
+            String beanName = UserConstants.JWT_TOKEN_BEAN_NAME + entry.getKey();
+            JwtTool jwtTool = new JwtTool(entry.getValue());
+            SpringUtil.registerBean(beanName, jwtTool);
+        }
+    }
+
+}

+ 11 - 0
src/main/java/com/jzo2o/gateway/constants/UserConstants.java

@@ -0,0 +1,11 @@
+package com.jzo2o.gateway.constants;
+
+public class UserConstants {
+    /**
+     * 从网关传过来的用户类型
+     */
+    public static final String X_USER_TYPE = "X-User-Type";
+
+
+    public static final String JWT_TOKEN_BEAN_NAME = "jwtTokenBeanName-";
+}

+ 37 - 0
src/main/java/com/jzo2o/gateway/filter/AuthFilter.java

@@ -0,0 +1,37 @@
+package com.jzo2o.gateway.filter;
+
+import com.jzo2o.common.constants.ErrorInfo;
+import com.jzo2o.common.constants.HeaderConstants;
+import com.jzo2o.gateway.utils.GatewayWebUtils;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import static com.jzo2o.gateway.constants.UserConstants.X_USER_TYPE;
+
+/**
+ * nginx根据不同的端的访问地址在header头上标记出用户的类型,和token中的用户类型进行对比
+ */
+public class AuthFilter implements GatewayFilter {
+
+    public AuthFilter() {
+    }
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        // 来自token的用户类型
+        String userType = GatewayWebUtils.getRequestHeader(exchange, HeaderConstants.USER_TYPE);
+        // 来自网关的用户类型
+        String xUserType = GatewayWebUtils.getRequestHeader(exchange, X_USER_TYPE);
+        // 对比两个用户类型是否一致
+        if (xUserType.equals(userType)) {
+            return chain.filter(exchange);
+        }
+        //无访问权限返回
+        return GatewayWebUtils.toResponse(exchange,
+                ErrorInfo.Code.NO_PERMISSIONS,
+                ErrorInfo.Msg.NO_PERMISSIONS);
+
+    }
+}

+ 19 - 0
src/main/java/com/jzo2o/gateway/filter/AuthGatewayFilterFactory.java

@@ -0,0 +1,19 @@
+package com.jzo2o.gateway.filter;
+
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author itcast
+ */
+@Component
+public class AuthGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
+
+    @Override
+    public GatewayFilter apply(Object config) {
+        return new AuthFilter();
+    }
+
+
+}

+ 98 - 0
src/main/java/com/jzo2o/gateway/filter/TokenFilter.java

@@ -0,0 +1,98 @@
+package com.jzo2o.gateway.filter;
+
+
+import cn.hutool.core.util.IdUtil;
+import com.jzo2o.common.constants.ErrorInfo;
+import com.jzo2o.common.constants.HeaderConstants;
+import com.jzo2o.common.model.CurrentUserInfo;
+import com.jzo2o.common.utils.Base64Utils;
+import com.jzo2o.common.utils.JsonUtils;
+import com.jzo2o.common.utils.JwtTool;
+import com.jzo2o.common.utils.StringUtils;
+import com.jzo2o.gateway.properties.ApplicationProperties;
+import com.jzo2o.gateway.utils.GatewayWebUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+
+/**
+ * token解析过滤器
+ *
+ * @author 86188
+ */
+@Slf4j
+public class TokenFilter implements GatewayFilter {
+
+    /**
+     * token header名称
+     */
+    private static final String HEADER_TOKEN = "Authorization";
+
+    private ApplicationProperties applicationProperties;
+
+    public TokenFilter(ApplicationProperties applicationProperties) {
+        this.applicationProperties = applicationProperties;
+    }
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+
+        // 1.黑名单和白名单校验
+        // 1.1.黑名单校验
+        String uri = GatewayWebUtils.getUri(exchange);
+        log.info("uri : {}", uri);
+
+
+        if (applicationProperties.getAccessPathBlackList().contains(uri)) {
+            return GatewayWebUtils.toResponse(exchange,
+                    HttpStatus.FORBIDDEN.value(),
+                    ErrorInfo.Msg.REQUEST_FORBIDDEN);
+        }
+        // 1.2.访问白名单
+        if (applicationProperties.getAccessPathWhiteList().contains(uri)) {
+            return chain.filter(exchange);
+        }
+
+        // 2.获取token解析工具JwtTool工具
+        // 2.1.获取token
+        String token = GatewayWebUtils.getRequestHeader(exchange, HEADER_TOKEN);
+        if (StringUtils.isEmpty(token)) {
+            return GatewayWebUtils.toResponse(exchange,
+                    HttpStatus.FORBIDDEN.value(),
+                    ErrorInfo.Msg.REQUEST_FORBIDDEN);
+        }
+        // 2.2.获取tokenKey
+        String tokenKey = applicationProperties.getTokenKey().get(JwtTool.getUserType(token) + "");
+        if (StringUtils.isEmpty(token)) {
+            return GatewayWebUtils.toResponse(exchange,
+                    HttpStatus.FORBIDDEN.value(),
+                    ErrorInfo.Msg.REQUEST_FORBIDDEN);
+        }
+        // 2.3.新建toekn解析工具对象jwtToken
+        JwtTool jwtTool = new JwtTool(tokenKey);
+
+        // 3.token解析
+        CurrentUserInfo currentUserInfo = jwtTool.parseToken(token);
+        if (currentUserInfo == null) {
+            return GatewayWebUtils.toResponse(exchange,
+                    HttpStatus.FORBIDDEN.value(), "登录过期或访问被拒绝");
+        }
+        // 4.用户id和用户类型向后传递
+        String userInfo = Base64Utils.encodeStr(JsonUtils.toJsonStr(currentUserInfo));
+
+        // 4.1.设置用户信息向下传递
+        GatewayWebUtils.setRequestHeader(exchange,
+                HeaderConstants.USER_INFO, userInfo);
+        // 4.2.设置用户类型向下传递
+        GatewayWebUtils.setRequestHeader(exchange,
+                HeaderConstants.USER_TYPE, currentUserInfo.getUserType() + "");
+        // 4.3.请求id
+        GatewayWebUtils.setRequestHeader(exchange, HeaderConstants.REQUEST_ID, IdUtil.getSnowflakeNextIdStr());
+        // 4.请求放行
+        return chain.filter(exchange);
+    }
+}

+ 26 - 0
src/main/java/com/jzo2o/gateway/filter/TokenGatewayFilterFactory.java

@@ -0,0 +1,26 @@
+package com.jzo2o.gateway.filter;
+
+import com.jzo2o.gateway.properties.ApplicationProperties;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * @author 86188
+ */
+@Component
+public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
+
+    @Resource
+    private ApplicationProperties applicationProperties;
+
+    public TokenGatewayFilterFactory() {
+    }
+
+    @Override
+    public GatewayFilter apply(Object config) {
+        return new TokenFilter(applicationProperties);
+    }
+}

+ 20 - 0
src/main/java/com/jzo2o/gateway/model/Result.java

@@ -0,0 +1,20 @@
+package com.jzo2o.gateway.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Result<T> {
+    public static final String REQUEST_OK = "OK";
+    private int code;
+    private String msg;
+    private T data;
+    private String requestId;
+
+    public static Result<?> error(int code, String msg) {
+        return new Result<>(code, msg, null, null);
+    }
+}

+ 43 - 0
src/main/java/com/jzo2o/gateway/properties/ApplicationProperties.java

@@ -0,0 +1,43 @@
+package com.jzo2o.gateway.properties;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.NestedConfigurationProperty;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Configuration
+@ConfigurationProperties(prefix = "jzo2o")
+@Data
+@Slf4j
+public class ApplicationProperties {
+
+    /**
+     * 每一个端都要配置一个token解析key
+     * “1”:xxx c端用户token生成key
+     * "2": xxx 服务端用户token生成key
+     * "3": xxx 机构端用户token生成key
+     * "4": xxx 运营端用户token生成key
+     * tokenkey
+     */
+    @NestedConfigurationProperty
+    private final Map<String,String> tokenKey = new HashMap<>();
+
+    /**
+     * 访问路径地址白名单
+     */
+    @NestedConfigurationProperty
+    private List<String> accessPathWhiteList = new ArrayList<>();
+
+    /**
+     * 访问路径黑名单
+     */
+    @NestedConfigurationProperty
+    private List<String> accessPathBlackList = new ArrayList<>();
+
+}

+ 168 - 0
src/main/java/com/jzo2o/gateway/utils/GatewayWebUtils.java

@@ -0,0 +1,168 @@
+package com.jzo2o.gateway.utils;
+
+import cn.hutool.core.lang.ObjectId;
+import com.jzo2o.common.utils.*;
+import com.jzo2o.gateway.model.Result;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.PathContainer;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * @author 86188
+ */
+public class GatewayWebUtils {
+
+    /**
+     * 网关请求输出数据
+     *
+     * @param exchange
+     * @param code
+     * @param message
+     * @return
+     */
+    public static Mono<Void> toResponse(ServerWebExchange exchange, int code, String message) {
+        // 设置返回码
+        exchange.getResponse()
+                .setStatusCode(HttpStatus.OK);
+        // 返回信息
+        Result result = Result.error(code, message);
+
+        DataBuffer dataBuffer = exchange.getResponse()
+                .bufferFactory()
+                .wrap(JsonUtils.toJsonStr(result)
+                        .getBytes(StandardCharsets.UTF_8));
+        ServerHttpResponse response = exchange.getResponse();
+        response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json");
+
+        return exchange.getResponse()
+                .writeWith(Flux.just(dataBuffer));
+    }
+
+    /**
+     * 比较method方法是否相同
+     *
+     * @param exchange
+     * @param httpMethod
+     * @return
+     */
+    public static boolean methodEqual(ServerWebExchange exchange, HttpMethod httpMethod) {
+        return getHttpMethtod(exchange).compareTo(httpMethod) == 0;
+    }
+
+    /**
+     * 根据header名称获取header值
+     *
+     * @param exchange
+     * @param headerName
+     * @return
+     */
+    public static String getRequestHeader(ServerWebExchange exchange, String headerName) {
+        return exchange.getRequest()
+                .getHeaders()
+                .getFirst(headerName);
+    }
+
+    public static String getRequestParameter(ServerWebExchange exchange, String parameterName) {
+        return exchange.getRequest()
+                .getQueryParams()
+                .getFirst(parameterName);
+    }
+
+    public static String getUri(ServerWebExchange exchange) {
+        URI uri = exchange.getRequest().getURI();
+        return uri.getPath();
+
+    }
+    /**
+     * 请求header中设置
+     *
+     * @param exchange
+     * @param headerName
+     * @param headerValue
+     */
+    public static void setRequestHeader(ServerWebExchange exchange, String headerName, String headerValue) {
+        exchange.mutate()
+                .request(builder -> builder.header(headerName, headerValue))
+                .build();
+    }
+
+    /**
+     * 设置多个请求header
+     *
+     * @param exchange
+     * @param headers  headers中包含header名称和header值,headers的数量是偶数,header名称在前,header值在后,该字段不能传控
+     */
+    public static void setManyRequestHeader(ServerWebExchange exchange, String... headers) {
+
+        ServerWebExchange.Builder mutate = exchange.mutate();
+        for (int count = 0; count < ArrayUtils
+                .length(headers); count += 2) {
+            String headerName = headers[count];
+            String headerValue = headers[count + 1];
+            mutate.request(builder -> builder.header(headerName, headerValue));
+        }
+        mutate.build();
+    }
+
+    /**
+     * 获取访问地址授权路径,例如get /evaluations/1,路径为EVALUATIONS:GET
+     * 注意:路径中的数字,mongo生成id不作为权限配置的部分
+     *
+     * @param exchange
+     * @return
+     */
+    public static String getAuthPath(ServerWebExchange exchange) {
+        // 1.请求路径
+        List<PathContainer.Element> pathElements = exchange.getRequest().getPath().elements();
+        StringBuffer buffer = new StringBuffer();
+        // 2.路径遍历(从后向前遍历),且拼接成权限路径
+        pathElements = CollUtils.reverse(new ArrayList<>(pathElements));
+        pathElements.stream()
+                // 过滤掉/、id(id是mongo自动生成的)和纯数字
+                .filter(element -> !element.value().equals(StringUtils.SLASH) && !ObjectId.isValid(element.value()) && !NumberUtils.isNumber(element.value()))
+                .forEach(element -> buffer.insert(0, StringUtils.DOT).insert(0, element.value()));
+
+        if (buffer.length() > 0) {
+            buffer.deleteCharAt(buffer.length() - 1);
+        }
+        // 3.将请求方法拼接到权限路径中
+        buffer.append(StringUtils.COLON)
+                .append(getMethod(exchange));
+        return buffer.toString();
+    }
+
+    /**
+     * 获取请求httpmethod
+     *
+     * @param exchange
+     * @return
+     */
+    public static HttpMethod getHttpMethtod(ServerWebExchange exchange) {
+        return exchange.getRequest()
+                .getMethod();
+    }
+
+    /**
+     * 获取字符串请求方法
+     *
+     * @param exchange
+     * @return
+     */
+    public static String getMethod(ServerWebExchange exchange) {
+        return getHttpMethtod(exchange)
+                .toString();
+    }
+
+}

+ 14 - 0
src/main/resources/bootstrap-dev.yml

@@ -0,0 +1,14 @@
+spring:
+  cloud:
+    nacos:
+      username: nacos
+      password: nacos
+      server-addr: 192.168.101.68:8848
+      config:
+        namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63
+        file-extension: yaml
+      discovery:
+        namespace: 75a593f5-33e6-4c65-b2a0-18c403d20f63
+logging:
+  level:
+    com.jzo2o: debug

+ 14 - 0
src/main/resources/bootstrap-prod.yml

@@ -0,0 +1,14 @@
+spring:
+  cloud:
+    nacos:
+      username: ${NACOS_USERNAME}
+      password: ${NACOS_PASSWORD}
+      server-addr: ${NACOS_ADDR}
+      config:
+        namespace: ${NACOS_NAMESPACE}
+        file-extension: yaml
+      discovery:
+        namespace: ${NACOS_NAMESPACE}
+logging:
+  level:
+    com.jzo2o: debug

+ 14 - 0
src/main/resources/bootstrap-test.yml

@@ -0,0 +1,14 @@
+spring:
+  cloud:
+    nacos:
+      username: ${NACOS_USERNAME}
+      password: ${NACOS_PASSWORD}
+      server-addr: ${NACOS_ADDR}
+      config:
+        namespace: ${NACOS_NAMESPACE}
+        file-extension: yaml
+      discovery:
+        namespace: ${NACOS_NAMESPACE}
+logging:
+  level:
+    com.jzo2o: debug

+ 118 - 0
src/main/resources/bootstrap.yml

@@ -0,0 +1,118 @@
+server:
+  port: 11500  #端口
+  tomcat:
+    uri-encoding: UTF-8   #服务编码
+spring:
+  profiles:
+    active: dev
+  application:
+    name: jzo2o-gateway
+  cloud:
+    nacos:
+      config:
+        file-extension: yaml
+        shared-configs: # 共享配置
+          - data-id: shared-spring.yaml # 共享spring配置
+            refresh: false
+          - data-id: shared-redis.yaml # 共享redis配置
+            refresh: false
+          - data-id: shared-logs.yaml # 共享日志配置
+            refresh: false
+    gateway:
+      routes:
+        # 运营端专用,供路由转发
+        - id: foundations
+          uri: lb://jzo2o-foundations
+          predicates:
+            - Path=/foundations/**
+          filters:
+            - Token
+        - id: orders-dispatch
+          uri: lb://jzo2o-orders-dispatch
+          predicates:
+            - Path=/orders-dispatch/**
+          filters:
+            - Token
+        - id: orders-seize
+          uri: lb://jzo2o-orders-seize
+          predicates:
+            - Path=/orders-seize/**
+          filters:
+            - Token
+        - id: orders-manager
+          uri: lb://jzo2o-orders-manager
+          predicates:
+            - Path=/orders-manager/**
+          filters:
+            - Token
+        - id: orders-history
+          uri: lb://jzo2o-orders-history
+          predicates:
+            - Path=/orders-history/**
+          filters:
+            - Token
+        - id: publics
+          uri: lb://jzo2o-publics
+          predicates:
+            - Path=/publics/**
+          filters:
+            - Token
+        - id: customer
+          uri: lb://jzo2o-customer
+          predicates:
+            - Path=/customer/**
+          filters:
+            - Token
+        - id: trade
+          uri: lb://jzo2o-trade
+          predicates:
+            - Path=/trade/**
+          filters:
+            - Token
+        - id: market
+          uri: lb://jzo2o-market
+          predicates:
+            - Path=/market/**
+          filters:
+            - Token
+        - id: health
+          uri: lb://jzo2o-health
+          predicates:
+            - Path=/health/**
+      globalcors: # 全局的跨域处理
+        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
+        corsConfigurations:
+          '[/**]':
+            allowedOriginPatterns: # 允许哪些网站的跨域请求
+              - "*"
+            allowedMethods: # 允许的跨域ajax的请求方式
+              - "GET"
+              - "POST"
+              - "DELETE"
+              - "PUT"
+              - "OPTIONS"
+            allowedHeaders: "*" # 允许在请求中携带的头信息
+            allowCredentials: true # 是否允许携带cookie
+            maxAge: 360000 # 这次跨域检测的有效期
+
+logging:
+  level:
+    com.jzo2o: debug
+jzo2o:
+  access-path-white-list:
+    - /foundations/open/login
+    - /customer/open/login/worker
+    - /customer/open/login/common/user
+    - /customer/open/serve-provider/institution/register
+    - /v3/api-docs/swagger-config
+    - /doc.html
+    - /operation/v2/api-docs
+    - /orders-dispatch/v2/api-docs
+    - /orders-manager/v2/api-docs
+    - /orders-seize/v2/api-docs
+    - /foundations/v2/api-docs
+    - /publics/v2/api-docs
+    - /publics/sms-code/send
+    - /customer/agency/serve-provider/institution/resetPassword
+    - /trade/open/notify/wx/1561414331
+    - /trade/open/notify/alipay/2088241317544335