.gitignore
@@ -1,12 +1,46 @@ *.class ###################################################################### # Build Tools # Mobile Tools for Java (J2ME) .mtj.tmp/ .gradle /build/ !gradle/wrapper/gradle-wrapper.jar # Package Files # *.jar *.war *.ear target/ !.mvn/wrapper/maven-wrapper.jar # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ###################################################################### # IDE ### STS ### .apt_generated .classpath .factorypath .project .settings .springBeans ### IntelliJ IDEA ### .idea *.iws *.iml *.ipr ### JRebel ### rebel.xml ### NetBeans ### nbproject/private/ build/* nbbuild/ dist/ nbdist/ .nb-gradle/ ###################################################################### # Others *.log *.xml.versionsBackup *.swp !*/build/*.java !*/build/*.html !*/build/*.xml pom.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,193 @@ <?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> <groupId>com.terra</groupId> <artifactId>terra</artifactId> <version>1.0.2</version> <name>terra</name> <url>https://www.smartearth.cn/</url> <description>å¾®æå¡ç³»ç»</description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-boot.version>2.7.18</spring-boot.version> <spring-cloud.version>2021.0.9</spring-cloud.version> <spring-cloud-alibaba.version>2021.0.6.1</spring-cloud-alibaba.version> <spring-boot-admin.version>2.7.16</spring-boot-admin.version> <tobato.version>1.27.2</tobato.version> <kaptcha.version>2.3.3</kaptcha.version> <pagehelper.boot.version>2.0.0</pagehelper.boot.version> <druid.version>1.2.23</druid.version> <dynamic-ds.version>4.3.1</dynamic-ds.version> <commons.io.version>2.19.0</commons.io.version> <velocity.version>2.3</velocity.version> <fastjson.version>2.0.57</fastjson.version> <jjwt.version>0.9.1</jjwt.version> <minio.version>8.2.2</minio.version> <poi.version>4.1.2</poi.version> <springdoc.version>1.6.9</springdoc.version> <transmittable-thread-local.version>2.14.4</transmittable-thread-local.version> <!-- override dependency version --> <tomcat.version>9.0.106</tomcat.version> <logback.version>1.2.13</logback.version> <spring-framework.version>5.3.39</spring-framework.version> </properties> <!-- ä¾èµå£°æ --> <dependencyManagement> <dependencies> <!-- è¦çSpringFrameworkçä¾èµé ç½®--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>${spring-framework.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- SpringCloud å¾®æå¡ --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- SpringCloud Alibaba å¾®æå¡ --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- SpringBoot ä¾èµé ç½® --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- è¦çlogbackçä¾èµé ç½®--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- è¦çtomcatçä¾èµé ç½®--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-websocket</artifactId> <version>${tomcat.version}</version> </dependency> <!-- JSON è§£æå¨åçæå¨ --> <dependency> <groupId>com.alibaba.fastjson2</groupId> <artifactId>fastjson2</artifactId> <version>${fastjson.version}</version> </dependency> </dependencies> </dependencyManagement> <modules> <module>se-gateway</module> <module>se-system</module> </modules> <packaging>pom</packaging> <dependencies> <!-- bootstrap å¯å¨å¨ --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> </plugins> <pluginManagement> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </pluginManagement> </build> <repositories> <repository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>public</id> <name>aliyun nexus</name> <url>https://maven.aliyun.com/repository/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project> se-gateway/pom.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,93 @@ <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"> <parent> <groupId>com.terra</groupId> <artifactId>terra</artifactId> <version>1.0.2</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>se-gateway</artifactId> <description> ç½å ³æ¨¡å </description> <dependencies> <!-- SpringCloud Gateway --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- SpringCloud Alibaba Nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- SpringCloud Alibaba Nacos Config --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- SpringCloud Alibaba Sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- SpringCloud Alibaba Sentinel Gateway --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency> <!-- Sentinel Datasource Nacos --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-datasource-nacos</artifactId> </dependency> <!-- SpringBoot Actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- SpringCloud Loadbalancer --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> <!-- Springdoc --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-webflux-ui</artifactId> <version>${springdoc.version}</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>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> se-gateway/src/main/java/com/terra/gateway/SeGatewayApplication.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,20 @@ package com.terra.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * ç½å ³å¯å¨ç¨åº * * @author admin */ @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) public class SeGatewayApplication { public static void main(String[] args) { SpringApplication.run(SeGatewayApplication.class, args); System.out.println("----------ç½å ³æ¨¡åå¯å¨æå---------- \n"); } } se-gateway/src/main/java/com/terra/gateway/config/GatewayConfig.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,23 @@ package com.terra.gateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import com.terra.gateway.handler.SentinelFallbackHandler; /** * ç½å ³éæµé ç½® * * @author admin */ @Configuration public class GatewayConfig { @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelFallbackHandler sentinelGatewayExceptionHandler() { return new SentinelFallbackHandler(); } } se-gateway/src/main/java/com/terra/gateway/config/SpringDocConfig.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,94 @@ package com.terra.gateway.config; import java.util.Set; import java.util.stream.Collectors; import org.springdoc.core.AbstractSwaggerUiConfigProperties; import org.springdoc.core.SwaggerUiConfigProperties; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.annotation.Configuration; import com.alibaba.nacos.client.naming.event.InstancesChangeEvent; import com.alibaba.nacos.common.notify.Event; import com.alibaba.nacos.common.notify.NotifyCenter; import com.alibaba.nacos.common.notify.listener.Subscriber; import javax.annotation.Resource; /** * SpringDocé 置类 * * @author admin */ @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "springdoc.api-docs.enabled", matchIfMissing = true) public class SpringDocConfig implements InitializingBean { @Autowired private SwaggerUiConfigProperties swaggerUiConfigProperties; @Autowired private DiscoveryClient discoveryClient; /** * å¨åå§ååè°ç¨çæ¹æ³ */ @Override public void afterPropertiesSet() { NotifyCenter.registerSubscriber(new SwaggerDocRegister(swaggerUiConfigProperties, discoveryClient)); } } /** * Swaggerææ¡£æ³¨åå¨ */ class SwaggerDocRegister extends Subscriber<InstancesChangeEvent> { @Resource private SwaggerUiConfigProperties swaggerUiConfigProperties; @Resource private DiscoveryClient discoveryClient; private final static String[] EXCLUDE_ROUTES = new String[] { "se-gateway", "se-auth", "se-file", "se-monitor", "se-system" }; public SwaggerDocRegister(SwaggerUiConfigProperties swaggerUiConfigProperties, DiscoveryClient discoveryClient) { this.swaggerUiConfigProperties = swaggerUiConfigProperties; this.discoveryClient = discoveryClient; } /** * äºä»¶åè°æ¹æ³ï¼å¤çInstancesChangeEventäºä»¶ * @param event äºä»¶å¯¹è±¡ */ @Override public void onEvent(InstancesChangeEvent event) { Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> swaggerUrlSet = discoveryClient.getServices() .stream() .flatMap(serviceId -> discoveryClient.getInstances(serviceId).stream()) //.filter(instance -> !StringUtils.equalsAnyIgnoreCase(instance.getServiceId(), EXCLUDE_ROUTES)) .map(instance -> { AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl = new AbstractSwaggerUiConfigProperties.SwaggerUrl(); swaggerUrl.setName(instance.getServiceId()); swaggerUrl.setUrl(String.format("/%s/v3/api-docs", instance.getServiceId())); return swaggerUrl; }) .collect(Collectors.toSet()); swaggerUiConfigProperties.setUrls(swaggerUrlSet); } /** * 订é ç±»åæ¹æ³ï¼è¿å订é çäºä»¶ç±»å * @return 订é çäºä»¶ç±»å */ @Override public Class<? extends Event> subscribeType() { return InstancesChangeEvent.class; } } se-gateway/src/main/java/com/terra/gateway/config/properties/IgnoreWhiteProperties.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,33 @@ package com.terra.gateway.config.properties; import java.util.ArrayList; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; /** * æ¾è¡ç½ååé ç½® * * @author admin */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.ignore") public class IgnoreWhiteProperties { /** * æ¾è¡ç½ååé ç½®ï¼ç½å ³ä¸æ ¡éªæ¤å¤çç½åå */ private List<String> whites = new ArrayList<>(); public List<String> getWhites() { return whites; } public void setWhites(List<String> whites) { this.whites = whites; } } se-gateway/src/main/java/com/terra/gateway/config/properties/XssProperties.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,48 @@ package com.terra.gateway.config.properties; import java.util.ArrayList; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; /** * XSSè·¨ç«èæ¬é ç½® * * @author admin */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.xss") public class XssProperties { /** * Xsså¼å ³ */ private Boolean enabled; /** * æé¤è·¯å¾ */ private List<String> excludeUrls = new ArrayList<>(); public Boolean getEnabled() { return enabled; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } public List<String> getExcludeUrls() { return excludeUrls; } public void setExcludeUrls(List<String> excludeUrls) { this.excludeUrls = excludeUrls; } } se-gateway/src/main/java/com/terra/gateway/filter/AuthFilter.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,128 @@ package com.terra.gateway.filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import com.terra.gateway.config.properties.IgnoreWhiteProperties; import reactor.core.publisher.Mono; import javax.annotation.Resource; /** * ç½å ³é´æ * * @author admin */ @Component public class AuthFilter implements GlobalFilter, Ordered { private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); // æé¤è¿æ»¤ç uri å°åï¼nacosèªè¡æ·»å @Resource private IgnoreWhiteProperties ignoreWhite; //@Resource //private RedisService redisService; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpRequest.Builder mutate = request.mutate(); String url = request.getURI().getPath(); /*// è·³è¿ä¸éè¦éªè¯çè·¯å¾ if (StringUtils.matches(url, ignoreWhite.getWhites())) { return chain.filter(exchange); } String token = getToken(request); if (StringUtils.isEmpty(token)) { return unauthorizedResponse(exchange, "令çä¸è½ä¸ºç©º"); } Claims claims = JwtUtils.parseToken(token); if (claims == null) { return unauthorizedResponse(exchange, "令çå·²è¿ææéªè¯ä¸æ£ç¡®ï¼"); } String userkey = JwtUtils.getUserKey(claims); boolean islogin = redisService.hasKey(getTokenKey(userkey)); if (!islogin) { return unauthorizedResponse(exchange, "ç»å½ç¶æå·²è¿æ"); } String userid = JwtUtils.getUserId(claims); String username = JwtUtils.getUserName(claims); if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) { return unauthorizedResponse(exchange, "令çéªè¯å¤±è´¥"); } // è®¾ç½®ç¨æ·ä¿¡æ¯å°è¯·æ± addHeader(mutate, SecurityConstants.USER_KEY, userkey); addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); // å é¨è¯·æ±æ¥æºåæ°æ¸ é¤ removeHeader(mutate, SecurityConstants.FROM_SOURCE);*/ return chain.filter(exchange.mutate().request(mutate.build()).build()); } private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) { if (value == null) { return; } String valueStr = value.toString(); //String valueEncode = ServletUtils.urlEncode(valueStr); //mutate.header(name, valueEncode); } private void removeHeader(ServerHttpRequest.Builder mutate, String name) { mutate.headers(httpHeaders -> httpHeaders.remove(name)).build(); } private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) { log.error("[é´æå¼å¸¸å¤ç]请æ±è·¯å¾:{},é误信æ¯:{}", exchange.getRequest().getPath(), msg); //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); return null; } /** * è·åç¼åkey */ private String getTokenKey(String token) { return null; //return CacheConstants.LOGIN_TOKEN_KEY + token; } /** * è·å请æ±token */ private String getToken(ServerHttpRequest request) { // String token = request.getHeaders().getFirst(SecurityConstants.AUTHORIZATION_HEADER); // // 妿å端设置äºä»¤çåç¼ï¼åè£åªæåç¼ // if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) // { // token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY); // } // return token; return null; } @Override public int getOrder() { return -200; } } se-gateway/src/main/java/com/terra/gateway/filter/BlackListUrlFilter.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,64 @@ package com.terra.gateway.filter; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.stereotype.Component; /** * é»ååè¿æ»¤å¨ * * @author admin */ @Component public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config> { @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { String url = exchange.getRequest().getURI().getPath(); if (config.matchBlacklist(url)) { //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请æ±å°åä¸å 许访é®"); } return chain.filter(exchange); }; } public BlackListUrlFilter() { super(Config.class); } public static class Config { private List<String> blacklistUrl; private List<Pattern> blacklistUrlPattern = new ArrayList<>(); public boolean matchBlacklist(String url) { return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); } public List<String> getBlacklistUrl() { return blacklistUrl; } public void setBlacklistUrl(List<String> blacklistUrl) { this.blacklistUrl = blacklistUrl; this.blacklistUrlPattern.clear(); this.blacklistUrl.forEach(url -> { this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); }); } } } se-gateway/src/main/java/com/terra/gateway/filter/XssFilter.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,128 @@ package com.terra.gateway.filter; import java.nio.charset.StandardCharsets; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 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.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import com.terra.gateway.config.properties.XssProperties; import io.netty.buffer.ByteBufAllocator; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; /** * è·¨ç«èæ¬è¿æ»¤å¨ * * @author admin */ @Component @ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true") public class XssFilter implements GlobalFilter, Ordered { // è·¨ç«èæ¬ç xss é ç½®ï¼nacosèªè¡æ·»å @Autowired private XssProperties xss; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); // xsså¼å ³æªå¼å¯ æ éè¿nacoså ³éï¼ä¸è¿æ»¤ if (!xss.getEnabled()) { return chain.filter(exchange); } // GET DELETE ä¸è¿æ»¤ HttpMethod method = request.getMethod(); if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) { return chain.filter(exchange); } // éjsonç±»åï¼ä¸è¿æ»¤ if (!isJsonRequest(exchange)) { return chain.filter(exchange); } // excludeUrls ä¸è¿æ»¤ String url = request.getURI().getPath(); // if (StringUtils.matches(url, xss.getExcludeUrls())) // { // return chain.filter(exchange); // } ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); } private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) { ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) { @Override public Flux<DataBuffer> getBody() { Flux<DataBuffer> body = super.getBody(); return body.buffer().map(dataBuffers -> { DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); DataBuffer join = dataBufferFactory.join(dataBuffers); byte[] content = new byte[join.readableByteCount()]; join.read(content); DataBufferUtils.release(join); String bodyStr = new String(content, StandardCharsets.UTF_8); // é²xssæ»å»è¿æ»¤ //bodyStr = EscapeUtil.clean(bodyStr); // 转æåè byte[] bytes = bodyStr.getBytes(StandardCharsets.UTF_8); NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); buffer.write(bytes); return buffer; }); } @Override public HttpHeaders getHeaders() { HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.putAll(super.getHeaders()); // ç±äºä¿®æ¹äºè¯·æ±ä½çbodyï¼å¯¼è´content-lengthé¿åº¦ä¸ç¡®å®ï¼å æ¤éè¦å é¤åå çcontent-length httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); return httpHeaders; } }; return serverHttpRequestDecorator; } /** * æ¯å¦æ¯Jsonè¯·æ± * * @param exchange HTTPè¯·æ± */ public boolean isJsonRequest(ServerWebExchange exchange) { String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); //return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); return true; } @Override public int getOrder() { return -100; } } se-gateway/src/main/java/com/terra/gateway/handler/GatewayExceptionHandler.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,56 @@ package com.terra.gateway.handler; import org.springframework.cloud.gateway.support.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * ç½å ³ç»ä¸å¼å¸¸å¤ç * * @author admin */ @Order(-1) @Configuration public class GatewayExceptionHandler implements ErrorWebExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); @Override public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { ServerHttpResponse response = exchange.getResponse(); if (exchange.getResponse().isCommitted()) { return Mono.error(ex); } String msg; if (ex instanceof NotFoundException) { msg = "æå¡æªæ¾å°"; } else if (ex instanceof ResponseStatusException) { ResponseStatusException responseStatusException = (ResponseStatusException) ex; msg = responseStatusException.getMessage(); } else { msg = "å 鍿å¡å¨é误"; } log.error("[ç½å ³å¼å¸¸å¤ç]请æ±è·¯å¾:{},å¼å¸¸ä¿¡æ¯:{}", exchange.getRequest().getPath(), ex.getMessage()); //return ServletUtils.webFluxResponseWriter(response, msg); return Mono.error(ex); } } se-gateway/src/main/java/com/terra/gateway/handler/SentinelFallbackHandler.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,41 @@ package com.terra.gateway.handler; import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebExceptionHandler; import reactor.core.publisher.Mono; /** * èªå®ä¹éæµå¼å¸¸å¤ç * * @author admin */ public class SentinelFallbackHandler implements WebExceptionHandler { private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) { //return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请æ±è¶ è¿æå¤§æ°ï¼è¯·ç¨ååè¯"); return null; } @Override public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { if (exchange.getResponse().isCommitted()) { return Mono.error(ex); } if (!BlockException.isBlockException(ex)) { return Mono.error(ex); } return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); } private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) { return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); } } se-gateway/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ Spring Boot Version: ${spring-boot.version} Spring Application Name: ${spring.application.name} _ | | __ _ __ _ | |_ ___ __ __ __ _ _ _ / _` | / _` || __| / _ \\ \ /\ / / / _` || | | | | (_| || (_| || |_ | __/ \ V V / | (_| || |_| | \__, | \__,_| \__| \___| \_/\_/ \__,_| \__, | __/ | __/ | |___/ |___/ se-gateway/src/main/resources/bootstrap.yml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,42 @@ # Tomcat server: port: 8080 # Spring spring: application: # åºç¨åç§° name: se-gateway profiles: # ç¯å¢é ç½® active: dev cloud: nacos: username: nacos password: nAcos_!9#_admIn discovery: # æå¡æ³¨åå°å server-addr: 127.0.0.1:8848 config: # é ç½®ä¸å¿å°å server-addr: 127.0.0.1:8848 # é ç½®æä»¶æ ¼å¼ file-extension: yml # å ±äº«é ç½® shared-configs: - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} sentinel: # åæ¶æ§å¶å°æå è½½ eager: true transport: # æ§å¶å°å°å dashboard: 127.0.0.1:8718 # nacosé ç½®æä¹ å datasource: ds1: nacos: server-addr: 127.0.0.1:8848 dataId: sentinel-se-gateway groupId: DEFAULT_GROUP data-type: json rule-type: gw-flow se-gateway/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,74 @@ <?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- æ¥å¿åæ¾è·¯å¾ --> <property name="log.path" value="logs/se-gateway" /> <!-- æ¥å¿è¾åºæ ¼å¼ --> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <!-- æ§å¶å°è¾åº --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- ç³»ç»æ¥å¿è¾åº --> <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/info.log</file> <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- æ¥å¿æä»¶åæ ¼å¼ --> <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- æ¥å¿æå¤§çåå² 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- è¿æ»¤ççº§å« --> <level>INFO</level> <!-- å¹é æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> <onMatch>ACCEPT</onMatch> <!-- ä¸å¹é æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/error.log</file> <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- æ¥å¿æä»¶åæ ¼å¼ --> <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- æ¥å¿æå¤§çåå² 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- è¿æ»¤ççº§å« --> <level>ERROR</level> <!-- å¹é æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> <onMatch>ACCEPT</onMatch> <!-- ä¸å¹é æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- ç³»ç»æ¨¡åæ¥å¿çº§å«æ§å¶ --> <logger name="com.terra" level="info" /> <!-- Springæ¥å¿çº§å«æ§å¶ --> <logger name="org.springframework" level="warn" /> <root level="info"> <appender-ref ref="console" /> </root> <!--ç³»ç»æä½æ¥å¿--> <root level="info"> <appender-ref ref="file_info" /> <appender-ref ref="file_error" /> </root> </configuration> se-system/pom.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,69 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>com.terra</groupId> <artifactId>terra</artifactId> <version>1.0.2</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>se-system</artifactId> <description> ç³»ç»æ¨¡å </description> <dependencies> <!-- SpringCloud Alibaba Nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- SpringCloud Alibaba Nacos Config --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!-- SpringCloud Alibaba Sentinel --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <!-- SpringBoot Actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Mysql Connector --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> se-system/src/main/java/com/terra/system/SeSystemApplication.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,19 @@ package com.terra.system; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * ç³»ç»æ¨¡å * * @author admin */ @SpringBootApplication public class SeSystemApplication { public static void main(String[] args) { SpringApplication.run(SeSystemApplication.class, args); System.out.println("----------ç³»ç»æ¨¡åå¯å¨æå---------- \n"); } } se-system/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ Spring Boot Version: ${spring-boot.version} Spring Application Name: ${spring.application.name} _ _ (_) | | _ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___ | '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \ | | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | | |_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_| __/ | __/ | |___/ |___/ se-system/src/main/resources/bootstrap.yml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,29 @@ # Tomcat server: port: 9201 # Spring spring: application: # åºç¨åç§° name: se-system profiles: # ç¯å¢é ç½® active: dev cloud: nacos: username: nacos password: nAcos_!9#_admIn discovery: # æå¡æ³¨åå°å server-addr: 127.0.0.1:8848 config: # é ç½®ä¸å¿å°å server-addr: 127.0.0.1:8848 # é ç½®æä»¶æ ¼å¼ file-extension: yml # å ±äº«é ç½® shared-configs: - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} # å è®¸å·æ° refresh-enabled: true se-system/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,74 @@ <?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- æ¥å¿åæ¾è·¯å¾ --> <property name="log.path" value="logs/se-system" /> <!-- æ¥å¿è¾åºæ ¼å¼ --> <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> <!-- æ§å¶å°è¾åº --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- ç³»ç»æ¥å¿è¾åº --> <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/info.log</file> <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- æ¥å¿æä»¶åæ ¼å¼ --> <fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- æ¥å¿æå¤§çåå² 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- è¿æ»¤ççº§å« --> <level>INFO</level> <!-- å¹é æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> <onMatch>ACCEPT</onMatch> <!-- ä¸å¹é æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${log.path}/error.log</file> <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- æ¥å¿æä»¶åæ ¼å¼ --> <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- æ¥å¿æå¤§çåå² 60天 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <pattern>${log.pattern}</pattern> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <!-- è¿æ»¤ççº§å« --> <level>ERROR</level> <!-- å¹é æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> <onMatch>ACCEPT</onMatch> <!-- ä¸å¹é æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- ç³»ç»æ¨¡åæ¥å¿çº§å«æ§å¶ --> <logger name="com.terra" level="info" /> <!-- Springæ¥å¿çº§å«æ§å¶ --> <logger name="org.springframework" level="warn" /> <root level="info"> <appender-ref ref="console" /> </root> <!--ç³»ç»æä½æ¥å¿--> <root level="info"> <appender-ref ref="file_info" /> <appender-ref ref="file_error" /> </root> </configuration>