feat: 应用开发后端基础框架,初始提交
diff --git a/bff/admin/Dockerfile b/bff/admin/Dockerfile
new file mode 100644
index 0000000..4810f6b
--- /dev/null
+++ b/bff/admin/Dockerfile
@@ -0,0 +1,21 @@
+FROM harbor.supwisdom.com/institute/openjdk:8-jre
+
+ENV ENABLE_JMX_SSL=false
+ENV JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dspring.profiles.active=docker
+ENV SPRING_PROFILES_ACTIVE=docker
+
+ARG NAME
+ARG VERSION
+ARG JAR_FILE
+
+LABEL name=$NAME \
+      version=$VERSION
+
+EXPOSE 8080
+
+EXPOSE 8443
+
+COPY --chown=java-app:java-app target/${JAR_FILE} /home/java-app/lib/app.jar
+
+COPY --chown=java-app:java-app target/doc /home/java-app/doc
+COPY --chown=java-app:java-app target/api-docs /home/java-app/api-docs
diff --git a/bff/admin/pom.xml b/bff/admin/pom.xml
new file mode 100644
index 0000000..5bc267a
--- /dev/null
+++ b/bff/admin/pom.xml
@@ -0,0 +1,247 @@
+<?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>
+    <groupId>com.supwisdom.institute</groupId>
+    <artifactId>sw-backend-parent</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <relativePath>../../</relativePath>
+  </parent>
+
+  <groupId>com.supwisdom.institute</groupId>
+  <artifactId>sw-backend-admin-bff</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <name>Supwisdom Backend Framework Admin Backend for Frontend</name>
+  <description>Supwisdom Backend Framework Admin Backend for Frontend project</description>
+
+  <properties>
+    <start-class>com.supwisdom.institute.admin.bff.Application</start-class>
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.projectlombok</groupId>
+      <artifactId>lombok</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>javax.servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+    </dependency>
+
+    <!-- 微服务 健康监控 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-actuator</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-webflux</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-gateway</artifactId>
+    </dependency>
+
+
+    <!-- <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-online-doc</artifactId>
+    </dependency> -->
+
+
+    <!-- <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-mvc</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-object-mapper</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-i18n</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-lang</artifactId>
+    </dependency> -->
+
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-security</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework.boot</groupId>
+          <artifactId>spring-boot-starter-web</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>io.jsonwebtoken</groupId>
+      <artifactId>jjwt</artifactId>
+      <version>0.9.1</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-cas</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.supwisdom.institute</groupId>
+      <artifactId>sw-backend-common-framework</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.alibaba</groupId>
+      <artifactId>fastjson</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+    </dependency>
+    <!-- <dependency>
+      <groupId>com.netflix.feign</groupId>
+      <artifactId>feign-httpclient</artifactId>
+    </dependency> -->
+
+
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger2</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.springfox</groupId>
+      <artifactId>springfox-swagger-ui</artifactId>
+    </dependency>
+
+
+    <!-- 热部署,无需重启项目 -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-devtools</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <finalName>${project.artifactId}</finalName>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-release-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
+
+
+      <!-- <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <configuration>
+          <encoding>${project.build.sourceEncoding}</encoding>
+        </configuration>
+        <executions>
+          <execution>
+            <id>copy-doc-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/doc</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../../doc</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-certs-jwt-resources</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <encoding>utf-8</encoding>
+              <outputDirectory>${basedir}/target/certs/jwt</outputDirectory>
+              <overwrite>true</overwrite>
+              <resources>
+                <resource>
+                  <directory>${basedir}/../../certs/jwt</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin> -->
+
+
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <groupId>com.spotify</groupId>
+        <artifactId>dockerfile-maven-plugin</artifactId>
+        <configuration>
+          <skip>false</skip>
+        </configuration>
+      </plugin>
+
+    </plugins>
+
+  </build>
+
+</project>
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java
new file mode 100644
index 0000000..364ed0b
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/Application.java
@@ -0,0 +1,49 @@
+package com.supwisdom.institute.backend.admin.bff;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+//import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+//import com.supwisdom.infras.online.doc.configuration.EnableInfrasOnlineDoc;
+import com.supwisdom.infras.security.configure.basic.EnableInfrasBasicApi;
+import com.supwisdom.infras.security.configure.cas.EnableInfrasCasSecurity;
+import com.supwisdom.infras.security.configure.jwt.EnableInfrasJWTApi;
+import com.supwisdom.institute.backend.common.core.transmit.annotation.EnableSimpleUserTransmit;
+
+@SpringBootApplication
+//@EnableFeignClients
+
+@EnableSimpleUserTransmit
+
+//@EnableInfrasOnlineDoc
+
+@EnableInfrasCasSecurity
+
+@EnableInfrasBasicApi
+@EnableInfrasJWTApi
+public class Application {
+
+  public static void main(String[] args) {
+    SpringApplication.run(Application.class, args);
+  }
+  
+  @Bean
+  public CorsFilter corsFilter() {
+    final CorsConfiguration config = new CorsConfiguration();
+    //config.setAllowCredentials(true);
+    config.addAllowedOrigin("*");
+    config.addAllowedHeader("*");
+    config.addAllowedMethod("*");
+
+    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+    source.registerCorsConfiguration("/v2/api-docs", config);
+    source.registerCorsConfiguration("/api/**", config);  // 对 /api/** 下的请求,支持 cors 跨域请求,如不需要可以注释
+
+    return new CorsFilter(source);
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/.gitkeep b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/.gitkeep
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/biz/AdminBizController.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/biz/AdminBizController.java
new file mode 100644
index 0000000..68bd37a
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/biz/AdminBizController.java
@@ -0,0 +1,17 @@
+package com.supwisdom.institute.backend.admin.bff.apis.controller.biz;
+
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(value = "/api/bff/v1/admin/biz")
+public class AdminBizController {
+
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String biz() {
+    return "biz";
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/system/AdminSystemController.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/system/AdminSystemController.java
new file mode 100644
index 0000000..84d0f3a
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/controller/system/AdminSystemController.java
@@ -0,0 +1,17 @@
+package com.supwisdom.institute.backend.admin.bff.apis.controller.system;
+
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping(value = "/api/bff/v1/admin/system")
+public class AdminSystemController {
+  
+  @RequestMapping(method = RequestMethod.GET, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  public String hello() {
+    return "hello";
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/remote/.gitkeep b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/remote/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/remote/.gitkeep
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/service/.gitkeep b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/service/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/service/.gitkeep
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/vo/.gitkeep b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/vo/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/apis/vo/.gitkeep
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java
new file mode 100644
index 0000000..2a22b46
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/FeignBasicAuthRequestInterceptor.java
@@ -0,0 +1,77 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * feign请求参数转化
+ * @author fengpy
+ */
+@Configuration
+public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    public FeignBasicAuthRequestInterceptor() {}
+
+    @Override
+    public void apply(RequestTemplate template) {
+        ///**get-pojo贯穿*/
+        if (template.method().equals("GET") && template.request().body() != null) {
+            try {
+                JsonNode jsonNode = objectMapper.readTree(template.request().body());
+                //template.body(null);
+                Map<String, Collection<String>> queries = new HashMap<>();
+                //feign 不支持 GET 方法传 POJO, json body转query
+                buildQuery(jsonNode, "", queries);
+                template.queries(queries);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //处理 get-pojo贯穿
+    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
+        if (!jsonNode.isContainerNode()) { //叶子节点
+            if (jsonNode.isNull()) {
+                return;
+            }
+            Collection<String> values = queries.get(path);
+            if (null == values) {
+                values = new ArrayList<>();
+                queries.put(path, values);
+            }
+            values.add(jsonNode.asText());
+            return;
+        }
+        if (jsonNode.isArray()) { //数组节点
+            Iterator<JsonNode> it = jsonNode.elements();
+            while (it.hasNext()) {
+                buildQuery(it.next(), path, queries);
+            }
+        } else {
+            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
+            while (it.hasNext()) {
+                Map.Entry<String, JsonNode> entry = it.next();
+                if (StringUtils.hasText(path)) {
+                    if ("mapBean".equals(path)||"orderBy".equals(path)||"sequence".equals(path)) {
+                        buildQuery(entry.getValue(), path + "[" + entry.getKey() + "]", queries);
+                    } else {
+                        buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
+                    }
+                } else { //根节点
+                    buildQuery(entry.getValue(), entry.getKey(), queries);
+                }
+            }
+        }
+    }
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GatewayFilterConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GatewayFilterConfig.java
new file mode 100644
index 0000000..f475158
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GatewayFilterConfig.java
@@ -0,0 +1,16 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.supwisdom.institute.backend.admin.bff.gateway.filter.factory.SimpleUserTransmitGatewayFilterFactory;
+
+@Configuration
+public class GatewayFilterConfig {
+
+  @Bean
+  public SimpleUserTransmitGatewayFilterFactory simpleUserTransmitGatewayFilterFactory() {
+    return new SimpleUserTransmitGatewayFilterFactory();
+  }
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GlobalFilterConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GlobalFilterConfig.java
new file mode 100644
index 0000000..e9e6282
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/GlobalFilterConfig.java
@@ -0,0 +1,16 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.supwisdom.institute.backend.admin.bff.gateway.filter.SimpleUserTransmitGlobalFilter;
+
+@Configuration
+public class GlobalFilterConfig {
+
+  @Bean
+  public SimpleUserTransmitGlobalFilter simpleUserTransmitGlobalFilter() {
+    return new SimpleUserTransmitGlobalFilter();
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/InfrasFilterSecurityInterceptorConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/InfrasFilterSecurityInterceptorConfig.java
new file mode 100644
index 0000000..6c77526
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/InfrasFilterSecurityInterceptorConfig.java
@@ -0,0 +1,53 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import com.supwisdom.infras.security.web.access.intercept.InfrasFilterSecurityInterceptor;
+import com.supwisdom.institute.backend.admin.bff.security.web.access.MyAccessDecisionManager;
+import com.supwisdom.institute.backend.admin.bff.security.web.access.intercept.InMemeryFilterInvocationSecurityMetadataSource;
+import com.supwisdom.institute.backend.admin.bff.security.web.access.intercept.MyFilterSecurityInterceptor;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Configuration
+public class InfrasFilterSecurityInterceptorConfig {
+
+//  @Bean
+//  public FilterInvocationSecurityMetadataSource securityMetadataSource() {
+//    MyFilterInvocationSecurityMetadataSource securityMetadataSource = new MyFilterInvocationSecurityMetadataSource();
+//    log.debug("InfrasFilterSecurityInterceptorConfig securityMetadataSource is {}", securityMetadataSource);
+//
+//    return securityMetadataSource;
+//  }
+  
+  @Bean
+  public FilterInvocationSecurityMetadataSource securityMetadataSource() {
+    InMemeryFilterInvocationSecurityMetadataSource securityMetadataSource = new InMemeryFilterInvocationSecurityMetadataSource();
+    log.debug("InfrasFilterSecurityInterceptorConfig securityMetadataSource is {}", securityMetadataSource);
+
+    return securityMetadataSource;
+  }
+  
+  
+  @Bean
+  public AccessDecisionManager accessDecisionManager() {
+    MyAccessDecisionManager accessDecisionManager = new MyAccessDecisionManager();
+    log.debug("InfrasFilterSecurityInterceptorConfig accessDecisionManager is {}", accessDecisionManager);
+
+    return accessDecisionManager;
+  }
+  
+  @Bean
+  public InfrasFilterSecurityInterceptor infrasFilterSecurityInterceptor() throws Exception {
+    MyFilterSecurityInterceptor myFilterSecurityInterceptor = new MyFilterSecurityInterceptor();
+    myFilterSecurityInterceptor.setRejectPublicInvocations(true);
+    log.debug("InfrasFilterSecurityInterceptorConfig infrasFilterSecurityInterceptor is {}", myFilterSecurityInterceptor);
+
+    return myFilterSecurityInterceptor;
+  }
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/ListenerConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/ListenerConfig.java
new file mode 100644
index 0000000..3f94d53
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/ListenerConfig.java
@@ -0,0 +1,27 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import com.supwisdom.institute.backend.admin.bff.listener.MyFilterInvocationSecurityMetadataSourceRefreshListener;
+
+@Configuration
+public class ListenerConfig {
+  
+  @Autowired
+  private FilterInvocationSecurityMetadataSource securityMetadataSource;
+  
+  @Bean
+  public ServletListenerRegistrationBean<MyFilterInvocationSecurityMetadataSourceRefreshListener> serssionListenerBean(){
+    MyFilterInvocationSecurityMetadataSourceRefreshListener listener = new MyFilterInvocationSecurityMetadataSourceRefreshListener();
+    listener.setSecurityMetadataSource(securityMetadataSource);
+    
+    ServletListenerRegistrationBean<MyFilterInvocationSecurityMetadataSourceRefreshListener> refreshListener = 
+        new ServletListenerRegistrationBean<MyFilterInvocationSecurityMetadataSourceRefreshListener>(listener);
+    return refreshListener;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/PasswordEncoderConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/PasswordEncoderConfig.java
new file mode 100644
index 0000000..b44d152
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/PasswordEncoderConfig.java
@@ -0,0 +1,29 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Configuration
+public class PasswordEncoderConfig {
+
+  @Bean
+  public PasswordEncoder passwordEncoder() {
+    
+    PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+
+    if (passwordEncoder instanceof DelegatingPasswordEncoder) {
+      ((DelegatingPasswordEncoder)passwordEncoder).setDefaultPasswordEncoderForMatches(NoOpPasswordEncoder.getInstance());
+    }
+
+    log.debug("PasswordEncoderConfig passwordEncoder is {}", passwordEncoder);
+    return passwordEncoder;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/UserDetailsServiceConfig.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/UserDetailsServiceConfig.java
new file mode 100644
index 0000000..63945f4
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/configuration/UserDetailsServiceConfig.java
@@ -0,0 +1,31 @@
+package com.supwisdom.institute.backend.admin.bff.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.supwisdom.institute.backend.admin.bff.security.core.userdetails.InMemeryUserDetailsService;
+import com.supwisdom.institute.backend.admin.bff.security.core.userdetails.MyUserDetailsService;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Configuration
+public class UserDetailsServiceConfig {
+
+//  @Bean
+//  public MyUserDetailsService userDetailsService() throws Exception {
+//    MyUserDetailsService myUserDetailsService = new MyUserDetailsService();
+//    log.debug("UserDetailsServiceConfig myUserDetailsService is {}", myUserDetailsService);
+//
+//    return myUserDetailsService;
+//  }
+
+  @Bean
+  public InMemeryUserDetailsService userDetailsService() throws Exception {
+    InMemeryUserDetailsService inMemeryUserDetailsService = new InMemeryUserDetailsService();
+    log.debug("UserDetailsServiceConfig inMemeryUserDetailsService is {}", inMemeryUserDetailsService);
+
+    return inMemeryUserDetailsService;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/SimpleUserTransmitGlobalFilter.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/SimpleUserTransmitGlobalFilter.java
new file mode 100644
index 0000000..a9bf2ae
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/SimpleUserTransmitGlobalFilter.java
@@ -0,0 +1,60 @@
+package com.supwisdom.institute.backend.admin.bff.gateway.filter;
+
+import java.net.URLDecoder;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.ReactiveSecurityContextHolder;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.web.server.ServerWebExchange;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.security.core.userdetails.MyUser;
+import com.supwisdom.institute.backend.common.core.transmit.user.User;
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+import reactor.core.publisher.Mono;
+
+@Slf4j
+public class SimpleUserTransmitGlobalFilter implements GlobalFilter, Ordered {
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
+
+  @Override
+  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+    
+    return ReactiveSecurityContextHolder.getContext()
+      .filter(c -> c.getAuthentication() != null && c.getAuthentication().isAuthenticated() && c.getAuthentication().getPrincipal() instanceof MyUser)
+      .map(SecurityContext::getAuthentication)
+      .map(Authentication::getPrincipal)
+      .cast(MyUser.class)
+      .map(myUser -> {
+        try {
+          User user = new User(myUser.getUsername(), myUser.getRoles(), myUser.getAttributes());
+          
+          String jsonUser = JSONObject.toJSONString(user);
+          log.info(jsonUser);
+          String headerValue = new String(URLDecoder.decode(jsonUser,"UTF-8"));
+          ServerHttpRequest request = exchange.getRequest().mutate()
+              .header(UserContext.KEY_USER_IN_HTTP_HEADER, headerValue)
+              .build();
+          log.debug("User set ok");
+          return exchange.mutate().request(request).build();
+        } catch (Exception e) {
+          log.warn("User set error", e);
+        }
+        return exchange;
+      })
+      .flatMap(ex -> chain.filter(ex))
+    ;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/factory/SimpleUserTransmitGatewayFilterFactory.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/factory/SimpleUserTransmitGatewayFilterFactory.java
new file mode 100644
index 0000000..6d0d981
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/filter/factory/SimpleUserTransmitGatewayFilterFactory.java
@@ -0,0 +1,93 @@
+package com.supwisdom.institute.backend.admin.bff.gateway.filter.factory;
+
+import java.net.URLDecoder;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.ReactiveSecurityContextHolder;
+import org.springframework.security.core.context.SecurityContext;
+
+import com.alibaba.fastjson.JSONObject;
+import com.supwisdom.institute.backend.admin.bff.security.core.userdetails.MyUser;
+import com.supwisdom.institute.backend.common.core.transmit.user.User;
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+@Slf4j
+public class SimpleUserTransmitGatewayFilterFactory extends AbstractGatewayFilterFactory<SimpleUserTransmitGatewayFilterFactory.Config> {
+  
+  public SimpleUserTransmitGatewayFilterFactory() {
+    super(Config.class);
+  }
+
+  @Override
+  public GatewayFilter apply(Config config) {
+    return (exchange, chain) -> {
+      
+      
+//      Mono<ServerWebExchange> m = Mono.fromCallable(() ->{
+//        MyUser myUser = ReactiveSecurityContextHolder.getContext()
+//            .filter(c -> c.getAuthentication() != null)
+//            .map(SecurityContext::getAuthentication)
+//            .map(Authentication::getPrincipal)
+//            .cast(MyUser.class)
+//            .block()
+//          ;
+//          try {
+//            String jsonUser = JSONObject.toJSONString(myUser);
+//            log.info(jsonUser);
+//            String headerValue = new String(URLDecoder.decode(jsonUser,"UTF-8"));
+//            ServerHttpRequest request = exchange.getRequest().mutate()
+//                .header(UserContext.KEY_USER_IN_HTTP_HEADER, headerValue)
+//                .build();
+//            log.debug("User set ok");
+//            return exchange.mutate().request(request).build();
+//          } catch (Exception e) {
+//            log.warn("User set error", e);
+//          }
+//          return exchange;
+//      })
+//      .publishOn(Schedulers.elastic())
+//      ;
+//      return m.flatMap(ex -> chain.filter(ex));
+
+      
+      return ReactiveSecurityContextHolder.getContext()
+          .filter(c -> c.getAuthentication() != null && c.getAuthentication().isAuthenticated() && c.getAuthentication().getPrincipal() instanceof MyUser)
+          .map(SecurityContext::getAuthentication)
+          .map(Authentication::getPrincipal)
+          .cast(MyUser.class)
+          .map(myUser -> {
+            try {
+              User user = new User(myUser.getUsername(), myUser.getRoles(), myUser.getAttributes());
+              
+              String jsonUser = JSONObject.toJSONString(user);
+              log.info(jsonUser);
+              String headerValue = new String(URLDecoder.decode(jsonUser,"UTF-8"));
+              ServerHttpRequest request = exchange.getRequest().mutate()
+                  .header(UserContext.KEY_USER_IN_HTTP_HEADER, headerValue)
+                  .build();
+              log.debug("User set ok");
+              return exchange.mutate().request(request).build();
+            } catch (Exception e) {
+              log.warn("User set error", e);
+            }
+            return exchange;
+          })
+          .flatMap(ex -> chain.filter(ex))
+        ;
+    };
+  }
+
+  public static class Config {
+    @Getter
+    @Setter
+    private String a;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/route/CustomRouteLocator.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/route/CustomRouteLocator.java
new file mode 100644
index 0000000..fc90c15
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/gateway/route/CustomRouteLocator.java
@@ -0,0 +1,17 @@
+package com.supwisdom.institute.backend.admin.bff.gateway.route;
+
+import org.springframework.cloud.gateway.route.Route;
+import org.springframework.cloud.gateway.route.RouteLocator;
+
+import reactor.core.publisher.Flux;
+
+public class CustomRouteLocator implements RouteLocator {
+
+  @Override
+  public Flux<Route> getRoutes() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/listener/MyFilterInvocationSecurityMetadataSourceRefreshListener.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/listener/MyFilterInvocationSecurityMetadataSourceRefreshListener.java
new file mode 100644
index 0000000..2c6d2bd
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/listener/MyFilterInvocationSecurityMetadataSourceRefreshListener.java
@@ -0,0 +1,59 @@
+package com.supwisdom.institute.backend.admin.bff.listener;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.servlet.ServletContextEvent;
+
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.web.context.ContextLoaderListener;
+
+import com.supwisdom.institute.backend.admin.bff.security.web.access.intercept.MyFilterInvocationSecurityMetadataSource;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MyFilterInvocationSecurityMetadataSourceRefreshListener extends ContextLoaderListener {
+
+  private FilterInvocationSecurityMetadataSource securityMetadataSource;
+  public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {
+    this.securityMetadataSource = securityMetadataSource;
+  }
+
+  private Timer timer = null;
+
+  private int delay = 1; // 启动后,延迟1分钟
+  private int period = 2; // 定时,每隔2分钟
+
+  @Override
+  public void contextInitialized(ServletContextEvent event) {
+    // super.contextInitialized(event);
+    log.info("MyFilterInvocationSecurityMetadataSourceRefreshListener.contextInitialized");
+
+    if (securityMetadataSource instanceof MyFilterInvocationSecurityMetadataSource) {
+      timer = new Timer("定时刷新权限信息", true);
+
+      timer.scheduleAtFixedRate(new TimerTask() {
+
+        @Override
+        public void run() {
+          ((MyFilterInvocationSecurityMetadataSource) securityMetadataSource).refreshRequestMap();
+        }
+
+      }, 1000 * 60 * delay, 1000 * 60 * period);
+
+    }
+
+  }
+
+  @Override
+  public void contextDestroyed(ServletContextEvent event) {
+    // super.contextDestroyed(event);
+    log.info("MyFilterInvocationSecurityMetadataSourceRefreshListener.contextDestroyed");
+
+    if (timer != null) {
+      timer.cancel();
+    }
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/InMemeryUserDetailsService.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/InMemeryUserDetailsService.java
new file mode 100644
index 0000000..bfe9a21
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/InMemeryUserDetailsService.java
@@ -0,0 +1,72 @@
+package com.supwisdom.institute.backend.admin.bff.security.core.userdetails;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import com.supwisdom.institute.backend.common.core.transmit.user.User;
+import com.supwisdom.institute.backend.common.core.transmit.user.UserContext;
+
+import reactor.core.publisher.Mono;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class InMemeryUserDetailsService implements UserDetailsService, ReactiveUserDetailsService {
+
+  @Autowired
+  PasswordEncoder passwordEncoder;
+  
+  @Override
+  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+    
+    log.debug("InMemeryUserDetailsService.loadUserByUsername({})", username);
+    
+    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+    authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
+    authorities.add(new SimpleGrantedAuthority("administrator"));
+    authorities.add(new SimpleGrantedAuthority("user"));
+
+    Map<String, Object> attributes = new HashMap<String, Object>();
+    
+    MyUser myUser = new MyUser(username, passwordEncoder.encode(username), authorities, attributes);
+    log.debug("myUser is {}", myUser);
+    
+    return myUser;
+  }
+
+  @Override
+  public Mono<UserDetails> findByUsername(String username) {
+
+    log.debug("InMemeryUserDetailsService.findByUsername({})", username);
+    
+    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+    authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
+    authorities.add(new SimpleGrantedAuthority("administrator"));
+    authorities.add(new SimpleGrantedAuthority("user"));
+
+    Map<String, Object> attributes = new HashMap<String, Object>();
+    
+    MyUser myUser = new MyUser(username, passwordEncoder.encode(username), authorities, attributes);
+    log.debug("myUser is {}", myUser);
+    
+    List<String> roles = new ArrayList<>();
+    roles.add("ROLE_ADMIN");
+    roles.add("administrator");
+    roles.add("user");
+    User user = new User(username, roles, attributes);
+    UserContext.setUser(user);
+    
+    return Mono.just(myUser);
+  }
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUser.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUser.java
new file mode 100644
index 0000000..b662422
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUser.java
@@ -0,0 +1,60 @@
+package com.supwisdom.institute.backend.admin.bff.security.core.userdetails;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+public class MyUser extends User {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 3195151947212484499L;
+
+  public MyUser(String username, String password, 
+      Collection<? extends GrantedAuthority> authorities, 
+      Map<String, Object> attributes) {
+    this(username, password, true, true, true, true, authorities, attributes);
+  }
+
+  public MyUser(String username, String password, 
+      boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, 
+      Collection<? extends GrantedAuthority> authorities, 
+      Map<String, Object> attributes) {
+    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
+    
+    this.attributes = attributes;
+  }
+
+  private final Map<String, Object> attributes;
+  public Map<String, Object> getAttributes() {
+    return this.attributes;
+  }
+  
+  public List<String> getRoles() {
+    List<String> roles = new ArrayList<>();
+    for (GrantedAuthority grantedAuthority : this.getAuthorities()) {
+      roles.add(grantedAuthority.getAuthority());
+    }
+    
+    return roles;
+  }
+  
+
+  public Object getAttribute(String key) {
+    if (attributes == null) {
+      return null;
+    }
+    
+    if (!attributes.containsKey(key)) {
+      return null;
+    }
+    
+    return attributes.get(key);
+  }
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUserDetailsService.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUserDetailsService.java
new file mode 100644
index 0000000..110af6b
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/core/userdetails/MyUserDetailsService.java
@@ -0,0 +1,79 @@
+package com.supwisdom.institute.backend.admin.bff.security.core.userdetails;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import reactor.core.publisher.Mono;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MyUserDetailsService implements UserDetailsService, ReactiveUserDetailsService {
+  
+  @Autowired
+  PasswordEncoder passwordEncoder;
+
+//  @Autowired
+//  AccountService accountService;
+  
+  @Override
+  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // TODO: 
+
+    log.debug("MyUserDetailsService.loadUserByUsername({})", username);
+    
+//    Account account = accountService.loadByUsername(username);
+//    if (account == null) {
+//      throw new UsernameNotFoundException(String.format("%s not found", username));
+//    }
+//    
+//    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+////    for (Role role : securityUser.getRoles()) {
+////      authorities.add(new SimpleGrantedAuthority(role.getCode()));
+////    }
+//    // FIXME: 
+//    authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
+//    authorities.add(new SimpleGrantedAuthority("administrator"));
+//    authorities.add(new SimpleGrantedAuthority("user"));
+//    
+//    Map<String, Object> attributes = new HashMap<String, Object>();
+//    attributes.put("userId", account.getUser().getId());
+//    attributes.put("userUid", account.getUser().getUid());
+//    
+//    MyUser myUser = new MyUser(
+//        account.getAccountName(), 
+//        account.getUser().getPassWord(), 
+//        account.getActivation() && "Normal".equals(account.getState()) ? true : false, 
+//        account.getAccountExpiryDate() == null || Calendar.getInstance().getTime().before(account.getAccountExpiryDate()) ? true : false,
+//        true, 
+//        true, 
+//        authorities,
+//        attributes);
+//    
+//    log.debug("myUser is {}", myUser);
+    
+    MyUser myUser = null;
+    
+    return myUser;
+  }
+
+  @Override
+  public Mono<UserDetails> findByUsername(String username) {
+    log.debug("MyUserDetailsService.findByUsername({})", username);
+    
+    MyUser myUser = null;
+    
+    return Mono.just(myUser);
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/MyAccessDecisionManager.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/MyAccessDecisionManager.java
new file mode 100644
index 0000000..56fe469
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/MyAccessDecisionManager.java
@@ -0,0 +1,48 @@
+package com.supwisdom.institute.backend.admin.bff.security.web.access;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+
+public class MyAccessDecisionManager implements AccessDecisionManager {
+
+  @Override
+  public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
+      throws AccessDeniedException, InsufficientAuthenticationException {
+
+    if (null == configAttributes || configAttributes.size() <= 0) {
+      return;
+    }
+    
+    ConfigAttribute ca;
+    String needRole;
+    for (Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext();) {
+      ca = iter.next();
+      needRole = ca.getAttribute();
+      for (GrantedAuthority ga : authentication.getAuthorities()) { // authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合
+        if (needRole.trim().equals(ga.getAuthority())) {
+          return;
+        }
+      }
+    }
+    
+    throw new AccessDeniedException("no right");
+  }
+
+  @Override
+  public boolean supports(ConfigAttribute attribute) {
+    return true;
+  }
+
+  @Override
+  public boolean supports(Class<?> clazz) {
+    return true;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/InMemeryFilterInvocationSecurityMetadataSource.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/InMemeryFilterInvocationSecurityMetadataSource.java
new file mode 100644
index 0000000..5666b1a
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/InMemeryFilterInvocationSecurityMetadataSource.java
@@ -0,0 +1,76 @@
+package com.supwisdom.institute.backend.admin.bff.security.web.access.intercept;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+public class InMemeryFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+  
+  private Map<RequestMatcher, Collection<ConfigAttribute>> requestMap = null;
+  
+  private void loadRequestMap() {
+    if (requestMap == null) {
+      requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();
+      
+      AntPathRequestMatcher requestMatcher0 = new AntPathRequestMatcher("/api/**");
+      Collection<ConfigAttribute> attributes0 = new ArrayList<ConfigAttribute>();  // FIXME: 返回当前请求的url 对应的 角色代码
+      attributes0.add(new SecurityConfig("user"));
+      requestMap.put(requestMatcher0, attributes0);
+
+      
+      AntPathRequestMatcher requestMatcher = new AntPathRequestMatcher("/web/**");
+      Collection<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();  // FIXME: 返回当前请求的url 对应的 角色代码
+      attributes.add(new SecurityConfig("user"));
+      requestMap.put(requestMatcher, attributes);
+    }
+  }
+
+  /**
+   * 获取当前请求关联的所有角色code {@link SecurityConfig} 
+   * 用于和用户拥有的角色code 进行比对
+   */
+  @Override
+  public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+    
+    if (requestMap == null) {
+      loadRequestMap();
+    }
+
+    HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
+    
+    RequestMatcher requestMatcher;
+    for(Iterator<RequestMatcher> iter = requestMap.keySet().iterator(); iter.hasNext(); ) {
+      requestMatcher = iter.next();
+      
+      if(requestMatcher.matches(request)) {
+        return requestMap.get(requestMatcher);
+      }
+    }
+    
+    return null;
+  }
+
+  @Override
+  public Collection<ConfigAttribute> getAllConfigAttributes() {
+
+    return null;
+  }
+
+  @Override
+  public boolean supports(Class<?> clazz) {
+
+    return true;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java
new file mode 100644
index 0000000..90f4b53
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterInvocationSecurityMetadataSource.java
@@ -0,0 +1,129 @@
+package com.supwisdom.institute.backend.admin.bff.security.web.access.intercept;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MyFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+  
+//  @Autowired
+//  User1SecurityPermissionRemoteService user1SecurityPermissionRemoteService;
+
+  private Map<RequestMatcher, Collection<ConfigAttribute>> requestMap = null;
+
+  public void refreshRequestMap() {
+    
+    log.info("MyFilterInvocationSecurityMetadataSource.refreshRequestMap");
+    
+    requestMap = null;
+    loadRequestMap();
+  }
+  
+  private void loadRequestMap() {
+    synchronized (MyFilterInvocationSecurityMetadataSource.class) {
+
+      if (requestMap == null) {
+        requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();
+        
+//        String applicationCode = Constants.APPLICATION_CODE;
+//        SecurityPermission securityPermission = user1SecurityPermissionRemoteService.loadPermissionsByAppcode(applicationCode, null);
+//        if (securityPermission == null) {
+//          return;
+//        }
+//  
+//        Map<String, String> mapRoles = new HashMap<String, String>();
+//        for (Role r : securityPermission.getRoles()) {
+//          mapRoles.put(r.getId(), r.getCode());
+//        }
+//  
+//        Map<String, Collection<ConfigAttribute>> permissionRoles = new HashMap<String, Collection<ConfigAttribute>>();
+//        for (RolePermission rp : securityPermission.getRolePermissions()) {
+//          if (mapRoles.containsKey(rp.getRoleId())) {
+//            if (!permissionRoles.containsKey(rp.getPermissionId())) {
+//              permissionRoles.put(rp.getPermissionId(), new ArrayList<ConfigAttribute>());
+//            }
+//            ConfigAttribute ca = new SecurityConfig(mapRoles.get(rp.getRoleId()));
+//            permissionRoles.get(rp.getPermissionId()).add(ca);
+//          }
+//        }
+//  
+//        for (Permission p : securityPermission.getPermissions()) {
+//          Collection<ConfigAttribute> attributes = permissionRoles.get(p.getId());
+//          if (attributes == null) {
+//            attributes = new ArrayList<ConfigAttribute>();
+//          }
+//          
+//          if (p.getUrl() == null || p.getUrl().isEmpty()) {
+//            continue;
+//          }
+//          
+//          String pattern = p.getUrl();
+//          String httpMethod = null;
+//          
+//          if (pattern.startsWith("GET ") || pattern.startsWith("POST ") || pattern.startsWith("PUT ") || pattern.startsWith("DELETE ")) {
+//            httpMethod = pattern.substring(0, pattern.indexOf(" "));
+//            pattern = pattern.substring(pattern.indexOf(" ")+1);
+//          }
+//          
+//          AntPathRequestMatcher requestMatcher = new AntPathRequestMatcher(pattern, httpMethod);
+//  
+//          requestMap.put(requestMatcher, attributes);
+//        }
+      }
+      
+    }
+  }
+
+  /**
+   * 获取当前请求关联的所有角色code {@link SecurityConfig} 用于和用户拥有的角色code 进行比对
+   */
+  @Override
+  public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
+
+    if (requestMap == null) {
+      loadRequestMap();
+    }
+
+    HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
+
+    RequestMatcher requestMatcher;
+    for (Iterator<RequestMatcher> iter = requestMap.keySet().iterator(); iter.hasNext();) {
+      requestMatcher = iter.next();
+
+      if (requestMatcher.matches(request)) {
+        return requestMap.get(requestMatcher);
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public Collection<ConfigAttribute> getAllConfigAttributes() {
+
+    return null;
+  }
+
+  @Override
+  public boolean supports(Class<?> clazz) {
+
+    return true;
+  }
+
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterSecurityInterceptor.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterSecurityInterceptor.java
new file mode 100644
index 0000000..7cd74e2
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/security/web/access/intercept/MyFilterSecurityInterceptor.java
@@ -0,0 +1,78 @@
+package com.supwisdom.institute.backend.admin.bff.security.web.access.intercept;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.SecurityMetadataSource;
+import org.springframework.security.access.intercept.InterceptorStatusToken;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+
+import com.supwisdom.infras.security.web.access.intercept.InfrasFilterSecurityInterceptor;
+import com.supwisdom.institute.backend.admin.bff.utils.AuthenticationUtil;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class MyFilterSecurityInterceptor extends InfrasFilterSecurityInterceptor {
+  
+  @Autowired
+  private FilterInvocationSecurityMetadataSource securityMetadataSource;
+
+  @Autowired
+  public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
+
+    super.setAccessDecisionManager(accessDecisionManager);
+  }
+
+  @Override
+  public void invoke(FilterInvocation fi) throws IOException, ServletException {
+    
+    Set<String> noneSecurityUrl = new HashSet<String>();  // FIXME: 对无须访问控制的url,支持可配置
+    noneSecurityUrl.add("/web/login");
+    noneSecurityUrl.add("/web/logout");
+    noneSecurityUrl.add("/web/index");
+
+    if (fi.getRequest() != null) {
+      String requestUrl = fi.getRequestUrl(); log.debug("MyFilterSecurityInterceptor invoke requestUrl: {}", requestUrl);
+      if (noneSecurityUrl.contains(requestUrl)) {
+        fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+        return;
+      }
+    }
+    
+    if(AuthenticationUtil.isAdministrator()){
+     fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+       return;
+  }
+    
+    // fi里面有一个被拦截的url
+    // 里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
+    // 再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
+    InterceptorStatusToken token = super.beforeInvocation(fi);
+    try {
+      // 执行下一个拦截器
+      fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+    } finally {
+      super.afterInvocation(token, null);
+    }
+  }
+
+  @Override
+  public Class<?> getSecureObjectClass() {
+
+    return FilterInvocation.class;
+  }
+
+  @Override
+  public SecurityMetadataSource obtainSecurityMetadataSource() {
+
+    return this.securityMetadataSource;
+  }
+  
+}
diff --git a/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/AuthenticationUtil.java b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/AuthenticationUtil.java
new file mode 100644
index 0000000..b2ab8e8
--- /dev/null
+++ b/bff/admin/src/main/java/com/supwisdom/institute/backend/admin/bff/utils/AuthenticationUtil.java
@@ -0,0 +1,91 @@
+package com.supwisdom.institute.backend.admin.bff.utils;
+
+import java.util.Collection;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import com.supwisdom.institute.backend.admin.bff.security.core.userdetails.MyUser;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class AuthenticationUtil {
+
+  public static String currentUsername() {
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+    if (authentication == null) {
+      log.error("authentication is null");
+      return null;
+    }
+
+    log.debug("authentication is {}", authentication.getPrincipal());
+
+    if (!authentication.isAuthenticated()) {
+      log.error("authentication is not authenticated");
+      return null;
+    }
+
+    if (authentication.getPrincipal() == null) {
+      log.error("authentication's principal is null");
+      return null;
+    }
+
+    log.debug("authentication's principal is {}", authentication.getPrincipal());
+
+    if (authentication.getPrincipal() instanceof MyUser) {
+      return ((MyUser) authentication.getPrincipal()).getUsername();
+    }
+
+    return null;
+  }
+
+  public static MyUser currentUser() {
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+    if (authentication == null) {
+      log.error("authentication is null");
+      return null;
+    }
+
+    log.debug("authentication is {}", authentication.getPrincipal());
+
+    if (!authentication.isAuthenticated()) {
+      log.error("authentication is not authenticated");
+      return null;
+    }
+
+    if (authentication.getPrincipal() == null) {
+      log.error("authentication's principal is null");
+      return null;
+    }
+
+    log.debug("authentication's principal is {}", authentication.getPrincipal());
+
+    if (authentication.getPrincipal() instanceof MyUser) {
+      return (MyUser) authentication.getPrincipal();
+    }
+
+    return null;
+  }
+
+  public static boolean isAdministrator() {
+    MyUser myUser = AuthenticationUtil.currentUser();
+    if (myUser != null) {
+      Collection<GrantedAuthority> grantedAuthoritys = myUser.getAuthorities();
+      if (grantedAuthoritys != null && grantedAuthoritys.size() > 0) {
+        for (GrantedAuthority grantedAuthority : grantedAuthoritys) {
+          if ("administrator".equals(grantedAuthority.getAuthority())) {
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+}
diff --git a/bff/admin/src/main/resources/application-docker.yml b/bff/admin/src/main/resources/application-docker.yml
new file mode 100644
index 0000000..cc5555e
--- /dev/null
+++ b/bff/admin/src/main/resources/application-docker.yml
@@ -0,0 +1,81 @@
+server:
+  port: ${SERVER_PORT:8443}
+  ssl:
+    enabled: ${SSL_ENABLED:true}
+    clientAuth: NEED
+    key-store: ${SSL_KEYSTORE_FILE:file:/certs/server/server.keystore}
+    key-store-password: ${SSL_KEYSTORE_PASSWORD:}
+    trust-store: ${SSL_TRUSTSTORE_FILE:file:/certs/server/server.truststore}
+    trust-store-password: ${SSL_TRUSTSTORE_PASSWORD:}
+  tomcat: 
+    accesslog: 
+      enabled: ${TOMCAT_ACCESSLOG_ENABLED:false}
+      buffered: ${TOMCAT_ACCESSLOG_BUFFERED:true}
+      directory: ${TOMCAT_ACCESSLOG_DIR:log}
+      prefix: ${TOMCAT_ACCESSLOG_PREFIX:sa-api-accesslog}
+      suffix: ${TOMCAT_ACCESSLOG_SUFFIX:.log}
+      file-date-format: ${TOMCAT_ACCESSLOG_FILE_DATE_FORMAT:.yyyy-MM-dd}
+      rotate: ${TOMCAT_ACCESSLOG_ROTATE:true}
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: INFO
+
+
+##
+# infras.online-doc
+#
+infras.online-doc.enabled: ${INFRAS_ONLINE_DOC_ENABLED:false}
+infras.online-doc.md-docs.staitc.path: ${INFRAS_ONLINE_DOC_MD_DOCS_STATIC_PATH:/doc/}
+infras.online-doc.api-docs.staitc.path: ${INFRAS_ONLINE_DOC_API_DOCS_STATIC_PATH:/api-docs/}
+
+
+##
+# infras.security basic
+#
+infras.security.basic.enabled: ${INFRAS_SECURITY_BASIC_ENABLED:true}
+
+
+##
+# infras.security jwt
+#
+infras.security.jwt.enabled: ${INFRAS_SECURITY_JWT_ENABLED:false}
+
+infras.security.jwt.public-key-pem: ${INFRAS_SECURITY_JWT_PUBLIC_KEY_PEM:}
+infras.security.jwt.private-key-pem-pkcs8: ${INFRAS_SECURITY_JWT_PRIVATE_KEY_PEM_PKCS8:}
+
+
+##
+# infras.security cas
+#
+infras.security.cas.enabled: ${INFRAS_SECURITY_CAS_ENABLED:false}
+
+#应用访问地址
+app.server.host.url: ${APP_SERVER_HOST_URL:https://localhost:8443}
+#应用登录地址
+app.login.url: ${APP_LOGIN_URL:/cas/login}
+#应用登出地址
+app.logout.url: ${APP_LOGOUT_URL:/cas/logout}
+
+#CAS服务地址
+cas.server.host.url: ${CAS_SERVER_HOST_URL:https://cas-server/cas}
+
+
+##
+# server url for feign
+#
+sw-backend-api-admin:
+  server:
+    url: ${CASSERVER_SA_API_SERVER_URL:https://sw-backend/sa-api}
+  client-auth:
+    enabled: ${CASSERVER_SA_API_CLIENT_AUTH_ENABLED:true}
+    key-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEY_PASSWORD:}
+    key-store: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_FILE:file:/certs/common/common.keystore}
+    key-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_KEYSTORE_PASSWORD:}
+    trust-store: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_FILE:file:/certs/common/common.truststore}
+    trust-store-password: ${CASSERVER_SA_API_CLIENT_AUTH_TRUSTSTORE_PASSWORD:}
diff --git a/bff/admin/src/main/resources/application.yml b/bff/admin/src/main/resources/application.yml
new file mode 100644
index 0000000..d93888b
--- /dev/null
+++ b/bff/admin/src/main/resources/application.yml
@@ -0,0 +1,114 @@
+server:
+  port: 8080
+
+
+##
+# logging
+#
+logging:
+  level:
+    root: INFO
+    com.supwisdom: DEBUG
+#    org.springframework.web: INFO
+#    org.springframework.cloud.openfeign: INFO
+
+
+spring:
+  jackson:
+    time-zone: Asia/Shanghai
+
+##
+# spring cloud gateway
+#
+  cloud:
+    gateway:
+      metrics:
+        enabled: true
+      routes:
+      - id: system-api
+        uri: http://localhost:8081
+        predicates:
+        - Path=/api/system/**
+        filters:
+        - RewritePath=/api/system/(?<suffix>.*), /$\{suffix}
+      - id: biz-api
+        uri: http://localhost:8081
+        predicates:
+        - Path=/api/biz/**
+        filters:
+        - RewritePath=/api/biz/(?<suffix>.*), /$\{suffix}
+
+
+feign:
+  client:
+    config:
+      default:
+        #errorDecoder: com.supwisdom.leaveschool.common.config.BaseExceptionErrorDecoder
+        connectTimeout: 12000
+        readTimeout: 12000
+        loggerLevel: full
+  hystrix:
+    enabled: true
+  httpclient:
+    enabled: true
+
+hystrix:
+  command:
+    default:
+      execution:
+        timeout:
+          enabled: true
+        isolation:
+          thread:
+            timeoutInMilliseconds: 12000
+
+
+##
+# infras.online-doc
+#
+infras.online-doc.enabled: false
+infras.online-doc.md-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/doc/
+infras.online-doc.api-docs.staitc.path: /Users/loie/c/work/git/institute/sw-backend/api-docs/
+
+
+##
+# infras.security basic
+#
+infras.security.basic.enabled: true
+
+
+##
+# infras.security jwt
+#
+infras.security.jwt.enabled: false
+
+#infras.security.jwt.public-key-pem: |-
+#  -----BEGIN PUBLIC KEY-----
+#  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBQw6TmvJ+nOuRaLoHsZJGIBzRg/wbskNv6UevL3/nQioYooptPfdIHVzPiKRVT5+DW5+nqzav3DOxY+HYKjO9nFjYdj0sgvRae6iVpa5Ji1wbDKOvwIDNukgnKbqvFXX2Isfl0RxeN3uEKdjeFGGFdr38I3ADCNKFNxtbmfqvjQIDAQAB
+#  -----END PUBLIC KEY-----
+#infras.security.jwt.private-key-pem-pkcs8: |-
+#  -----BEGIN PRIVATE KEY-----
+#  MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMFDDpOa8n6c65FougexkkYgHNGD/BuyQ2/pR68vf+dCKhiiim0990gdXM+IpFVPn4Nbn6erNq/cM7Fj4dgqM72cWNh2PSyC9Fp7qJWlrkmLXBsMo6/AgM26SCcpuq8VdfYix+XRHF43e4Qp2N4UYYV2vfwjcAMI0oU3G1uZ+q+NAgMBAAECgYA7jA7UuhxXmMAYmJ0hO7xnMQPQJouqeP3AYK9+sfMF7WQNHR/r0vj7Vli/dUm1I4hxr+x8fAuomf+ve6gds7sm+v2JHLzEIyPPiogoC7IcBmjJ3yVzW/26cXeOmTiPC/fW2g4BpYxSM8HLDaSkrtqzy8e9ijlzMpHBvvwLikufnQJBAOXaqIPuZ7Vm/JwQHAmX2HV+Qk6GMi/H7mL8X0AaW68w+Iccdbz1hzmMBfdn5NMmx2AOwoBAVivgjt0a1OfksHMCQQDXPtXxwFy4dQ4TbPu8L38P8s/bPo9ib1YkEMp57yBw+IvxB7jnpA9rUYTfZM/HpVP7r9rfVEUylVXXzhz1qx//AkEApWJOTBdW8bQ3YEdLFS/3pJqDNSLjq3OMuBZkpqgQfh6bRAQbRynW8XYpuNk9URye6iPUmRkxp4J86ORseqoWtwJAJb5a/b1hhObhxP5DVkht23oUgLmDoxsq28AmASOxaJ3szCMyhUv7eDIfPp0K4lNXWrcHhkncqHYPS3xVD68mOQJAV4SRDdWpgAbQOUODotohE48RxrabHo0l228CJ/pnm0q7gplPs4iSNJ2eijFuOMXfKkq3z/vxiNSA59FcdoCOHQ==
+#  -----END PRIVATE KEY-----
+
+
+##
+# infras.security cas
+#
+infras.security.cas.enabled: false
+
+#应用访问地址
+app.server.host.url: http://localhost:8080
+#应用登录地址
+app.login.url: /cas/login
+#应用登出地址
+app.logout.url: /cas/logout
+
+#CAS服务地址
+cas.server.host.url: https://cas.supwisdom.com/cas
+
+
+##
+# server url for feign
+#
+sw-backend-api-admin.server.url: http://localhost:8081
diff --git a/bff/admin/src/main/resources/bootstrap.yml b/bff/admin/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..2df1be7
--- /dev/null
+++ b/bff/admin/src/main/resources/bootstrap.yml
@@ -0,0 +1,3 @@
+spring:
+  application:
+    name: sw-backend-admin-bff