Compare commits
5 Commits
3e4a903554
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fea479a597 | ||
|
|
6951a2513f | ||
|
|
78a26b2ed2 | ||
|
|
d8c5c602a9 | ||
|
|
3aa39d37ce |
36
pom.xml
36
pom.xml
@@ -3,9 +3,9 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.xiang</groupId>
|
<groupId>com.xiang.pom</groupId>
|
||||||
<artifactId>xservice-basic</artifactId>
|
<artifactId>xmc-web-starter</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
@@ -56,6 +56,19 @@
|
|||||||
<version>${spring.boot.version}</version>
|
<version>${spring.boot.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Authorization Server -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-oauth2-authorization-server</artifactId>
|
||||||
|
<version>0.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- JWT (optional: for convenience) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||||
|
<version>5.7.11</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Lombok(可选,简化开发) -->
|
<!-- Lombok(可选,简化开发) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
@@ -69,18 +82,17 @@
|
|||||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.xiang</groupId>
|
<groupId>com.xiang.starter</groupId>
|
||||||
<artifactId>xservice-parent-starter</artifactId>
|
<artifactId>xmc-common</artifactId>
|
||||||
<version>2.0</version>
|
<version>1.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<!-- <dependency>-->
|
||||||
<groupId>com.xiang</groupId>
|
<!-- <groupId>com.xiang</groupId>-->
|
||||||
<artifactId>xservice-security-starter</artifactId>
|
<!-- <artifactId>xservice-security-starter</artifactId>-->
|
||||||
<version>1.0-SNAPSHOT</version>
|
<!-- <version>1.0-SNAPSHOT</version>-->
|
||||||
</dependency>
|
<!-- </dependency>-->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
26
xs-server/src/main/java/com/xiang/HealthController.java
Normal file
26
xs-server/src/main/java/com/xiang/HealthController.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.xiang;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
public class HealthController {
|
||||||
|
|
||||||
|
@Value("${spring.profiles.active}")
|
||||||
|
private String env;
|
||||||
|
|
||||||
|
@GetMapping("/actuator/health")
|
||||||
|
public Map<String, String> checkHealth() {
|
||||||
|
Map<String, String> map = Maps.newHashMap();
|
||||||
|
map.put("env", env);
|
||||||
|
map.put("status", "UP");
|
||||||
|
log.info("cornucopia application health check success! listening in env:{}, now:{}", env, System.currentTimeMillis());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,9 +9,11 @@ spring:
|
|||||||
cloud:
|
cloud:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
server-addr: general.xiangtech.xyz:8848
|
|
||||||
namespace: 00131110-3ecb-4a35-8bbb-624edde1d937
|
|
||||||
group: DEFAULT_GROUP
|
group: DEFAULT_GROUP
|
||||||
|
namespace: 6f603892-e9f7-4ca4-acbc-538fa09ebec0
|
||||||
|
server-addr: http://192.168.1.10:8848
|
||||||
|
# 是否启用健康检查
|
||||||
|
register-enabled: true
|
||||||
username: nacos
|
username: nacos
|
||||||
password: nacos
|
password: nacos
|
||||||
gateway:
|
gateway:
|
||||||
@@ -25,12 +27,24 @@ spring:
|
|||||||
- Path=/api-auth/**
|
- Path=/api-auth/**
|
||||||
filters:
|
filters:
|
||||||
- StripPrefix=1
|
- StripPrefix=1
|
||||||
|
- id: xservice-common-center
|
||||||
|
uri: lb://xservice-common-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-common/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- id: xservice-stock-center
|
||||||
|
uri: lb://xservice-stock-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-stock/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
||||||
port: 6379
|
port: 6379
|
||||||
password: Xiang0000 # 如果无密码可以省略
|
password: Xiang0000 # 如果无密码可以省略
|
||||||
database: 0
|
database: 10
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
lettuce:
|
lettuce:
|
||||||
pool:
|
pool:
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ spring:
|
|||||||
cloud:
|
cloud:
|
||||||
nacos:
|
nacos:
|
||||||
discovery:
|
discovery:
|
||||||
server-addr: general.xiangtech.xyz:8848
|
|
||||||
namespace: e4a9b94d-637e-4faf-8521-6ffc090a8c03
|
|
||||||
group: DEFAULT_GROUP
|
group: DEFAULT_GROUP
|
||||||
|
namespace: 00131110-3ecb-4a35-8bbb-624edde1d937
|
||||||
|
server-addr: http://general.xiangtech.xyz:8848
|
||||||
|
# 是否启用健康检查
|
||||||
|
register-enabled: false
|
||||||
username: nacos
|
username: nacos
|
||||||
password: nacos
|
password: nacos
|
||||||
gateway:
|
gateway:
|
||||||
@@ -25,12 +27,24 @@ spring:
|
|||||||
- Path=/api-auth/**
|
- Path=/api-auth/**
|
||||||
filters:
|
filters:
|
||||||
- StripPrefix=1
|
- StripPrefix=1
|
||||||
|
- id: xservice-common-center
|
||||||
|
uri: lb://xservice-common-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-common/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- id: xservice-stock-center
|
||||||
|
uri: lb://xservice-stock-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-stock/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
||||||
port: 6379
|
port: 6379
|
||||||
password: Xiang0000 # 如果无密码可以省略
|
password: Xiang0000 # 如果无密码可以省略
|
||||||
database: 0
|
database: 10
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
lettuce:
|
lettuce:
|
||||||
pool:
|
pool:
|
||||||
60
xs-server/src/main/resources/application-prod.yml
Normal file
60
xs-server/src/main/resources/application-prod.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
server:
|
||||||
|
port: 38010
|
||||||
|
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: xservice-gateway
|
||||||
|
main:
|
||||||
|
web-application-type: reactive # 强制使用 WebFlux
|
||||||
|
cloud:
|
||||||
|
nacos:
|
||||||
|
discovery:
|
||||||
|
group: DEFAULT_GROUP
|
||||||
|
namespace: 6f603892-e9f7-4ca4-acbc-538fa09ebec0
|
||||||
|
server-addr: http://192.168.32.3:8848
|
||||||
|
# 是否启用健康检查
|
||||||
|
register-enabled: true
|
||||||
|
username: nacos
|
||||||
|
password: nacos
|
||||||
|
gateway:
|
||||||
|
discovery:
|
||||||
|
locator:
|
||||||
|
enabled: true # 开启 nacos 自动路由
|
||||||
|
routes:
|
||||||
|
- id: xservice-auth-center
|
||||||
|
uri: lb://xservice-auth-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-auth/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- id: xservice-common-center
|
||||||
|
uri: lb://xservice-common-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-common/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- id: xservice-stock-center
|
||||||
|
uri: lb://xservice-stock-center
|
||||||
|
predicates:
|
||||||
|
- Path=/api-stock/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
- id: xservice-quartz-admin
|
||||||
|
uri: lb://xservice-quartz-admin
|
||||||
|
predicates:
|
||||||
|
- Path=/api-quartz/**
|
||||||
|
filters:
|
||||||
|
- StripPrefix=1
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: r-bp1wt59a6nfyt4e3ltpd.redis.rds.aliyuncs.com
|
||||||
|
port: 6379
|
||||||
|
password: Xiang0000 # 如果无密码可以省略
|
||||||
|
database: 0
|
||||||
|
timeout: 5000
|
||||||
|
lettuce:
|
||||||
|
pool:
|
||||||
|
max-active: 8
|
||||||
|
max-idle: 8
|
||||||
|
min-idle: 0
|
||||||
|
max-wait: 1000
|
||||||
28
xs-server/src/main/resources/keys/rsa-private.pem
Normal file
28
xs-server/src/main/resources/keys/rsa-private.pem
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD7JdqQe8W8byYT
|
||||||
|
KuPK7STLYO5TTe5uWhHj1SLq7Xoj1y0agO+x1X3/dUA1X/k5Dd2rmkmIU2VoB/9c
|
||||||
|
aoE5naXUhVfE9wDsl5AKdWRCn1PKvuofd/0kuGFS44tNQcLGtDD7e8CQQJZJPZVS
|
||||||
|
Z8F2nlHjYSTUPVvi77hKG21qoZLEa0F+TYfqgOohabQtxeBAnyRW50/g281Bqd3w
|
||||||
|
ntfM0aKfW9fsFhJnk+AlXWaqxQKkhtzMmKVeqLNfJnXvhgUA6QbnzHPtPxF+fLEx
|
||||||
|
BNnBEPF8CsQFVdt1TtsQlfCzVMTMibZU2CcwtqHUP1maEcH5zV5whPfgkahejiNm
|
||||||
|
L08Jw74VAgMBAAECggEACJHb0pGHh4IkF/XmM6Qs6xMFYmqmvRkf0JjoTYDl9+JW
|
||||||
|
Y9RMYKfqy+Yius+GSNRjPWS7p38MHkiysGL/F7uYyCwvhwU3x+kugM2+/+gWqyaT
|
||||||
|
WnwYgZ4YXIRu2ieFr4xq1symnzO14nDny4uqB9PEZFd7wS4I0ZShe5yLM6Yai88V
|
||||||
|
0Jm6Hi9RcC5efiE4tWismBKaP13WXamAVySROW30lEaMgyI66DNYgs+RHiZgAFP7
|
||||||
|
u7raUD07xrk6eV6YnG/9EvS/oqV+IPEacY+bP3ZUqvPMI50tLTEVN1yJXrr4T3kS
|
||||||
|
W1TiApaL87rdDCYem7rtIury+JcSadaI6lwP5OhmLwKBgQD/4mSrFi30IzD6LFam
|
||||||
|
N7CYBxSleWgha2fHuycDGNGcXDCn3y4JuqTMRpV1c9F5emPPv1E3ELj4plz/NnVr
|
||||||
|
67SkCs3nqoSRjyXJKhN/kJqM/NB+Ic1UgXeI+wGMkfkUHrQ6T6SghYVxWW+hQKm8
|
||||||
|
IeV7aVJiM01/Ze938cnJuWd17wKBgQD7QumZzRTMkmnmSFCpOhs2Y3B8JYrJsJXY
|
||||||
|
PeYkxea/7brDyuIdWKt0kl9EvpsrIzTe0t4LYV3Vmmfh15PNZp4PEr30NEBxeVOO
|
||||||
|
HoglNfyJgP/nvhOGYesNhqPlK96/ajEvu7FpFHwDje5RKRWxCK5qhZneDy0ppjWb
|
||||||
|
6seshN1wOwKBgQDqNPxxP/bFu6Qrh4Oz1cs0C18RakMuO5Gc1acKhZ/tntAGBxer
|
||||||
|
XgNS2dQY0e5MYwKSdwlN/mdfZ149Vko5gl8vupfmUEPQuxYZvwJjwyZCn2/x0tyO
|
||||||
|
WYXggeZUFJPHn6bUrGsBZdTS/8pV7Mqu4NOblrYKHez0C4gY390TXzjcTwKBgQDR
|
||||||
|
mD6fYrjf8Z7PTzGiCOucUhUKKpL8rgZBbVknAcL8BYZPP1Whn07fHh7EjK+Jq4O2
|
||||||
|
AHbjTWRmA7h2Z0tPAzQEZOD57gB35/pwSj3NtJwl4+sU2LUW22WlUdQ0HoVgbWf8
|
||||||
|
ZniWrFTK7kGHiFsk45YDG9F/sG8/F/wORSotWmQR8wKBgQDqrlyvMCwiJHW7vOPs
|
||||||
|
ih+utzIvtZ8D4fxzEFluTUqubAAl3N+81NuRJuEFIJLjIAeTNOHj1IdlPj5oe0aa
|
||||||
|
IYOzoB2+xJxnLPbvI1tTat/pqgXxPY24/9c9rBoTCsJboTPb0fMh1nHxTZvny4tB
|
||||||
|
jP7d5EBvIMWnCEuTo4y39ZFsMA==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
9
xs-server/src/main/resources/keys/rsa-public.pem
Normal file
9
xs-server/src/main/resources/keys/rsa-public.pem
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+yXakHvFvG8mEyrjyu0k
|
||||||
|
y2DuU03ubloR49Ui6u16I9ctGoDvsdV9/3VANV/5OQ3dq5pJiFNlaAf/XGqBOZ2l
|
||||||
|
1IVXxPcA7JeQCnVkQp9Tyr7qH3f9JLhhUuOLTUHCxrQw+3vAkECWST2VUmfBdp5R
|
||||||
|
42Ek1D1b4u+4ShttaqGSxGtBfk2H6oDqIWm0LcXgQJ8kVudP4NvNQand8J7XzNGi
|
||||||
|
n1vX7BYSZ5PgJV1mqsUCpIbczJilXqizXyZ174YFAOkG58xz7T8RfnyxMQTZwRDx
|
||||||
|
fArEBVXbdU7bEJXws1TEzIm2VNgnMLah1D9ZmhHB+c1ecIT34JGoXo4jZi9PCcO+
|
||||||
|
FQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.xiang.xservice.gateway.service.config;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.jwk.JWKSet;
|
||||||
|
import com.nimbusds.jose.jwk.RSAKey;
|
||||||
|
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||||
|
import com.nimbusds.jose.proc.SecurityContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||||
|
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
|
||||||
|
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class JwtConfig {
|
||||||
|
|
||||||
|
private RSAPrivateKey loadPrivateKey(String classpath) throws Exception {
|
||||||
|
InputStream is = new ClassPathResource(classpath).getInputStream();
|
||||||
|
String key = new String(is.readAllBytes(), StandardCharsets.UTF_8)
|
||||||
|
.replace("-----BEGIN PRIVATE KEY-----", "")
|
||||||
|
.replace("-----END PRIVATE KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(key));
|
||||||
|
return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RSAPublicKey loadPublicKey(String classpath) throws Exception {
|
||||||
|
InputStream is = new ClassPathResource(classpath).getInputStream();
|
||||||
|
String key = new String(is.readAllBytes(), StandardCharsets.UTF_8)
|
||||||
|
.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||||
|
.replace("-----END PUBLIC KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
X509EncodedKeySpec spec = new X509EncodedKeySpec(Base64.getDecoder().decode(key));
|
||||||
|
return (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JWKSource<SecurityContext> jwkSource() throws Exception {
|
||||||
|
// 使用RSA对称加密进行加密
|
||||||
|
RSAPublicKey publicKey = loadPublicKey("keys/rsa-public.pem");
|
||||||
|
RSAPrivateKey privateKey = loadPrivateKey("keys/rsa-private.pem");
|
||||||
|
|
||||||
|
RSAKey rsaKey = new RSAKey.Builder(publicKey)
|
||||||
|
.privateKey(privateKey)
|
||||||
|
.keyID("xservice")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
JWKSet jwkSet = new JWKSet(rsaKey);
|
||||||
|
return (jwkSelector, ctx) -> jwkSelector.select(jwkSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
|
||||||
|
return new NimbusJwtEncoder(jwkSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
|
||||||
|
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,30 @@
|
|||||||
package com.xiang.xservice.gateway.service.core;
|
package com.xiang.xservice.gateway.service.core;
|
||||||
|
|
||||||
import com.xiang.xservice.security.utils.TokenUtils;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.security.oauth2.jwt.Jwt;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtException;
|
||||||
|
import org.springframework.security.oauth2.jwt.JwtValidationException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
||||||
|
|
||||||
@Autowired
|
private final JwtDecoder jwtDecoder;
|
||||||
private TokenUtils tokenUtils;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
@@ -29,6 +35,7 @@ public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
|||||||
log.debug("跳过 Token 校验: {}", path);
|
log.debug("跳过 Token 校验: {}", path);
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
|
// todo open开放接口如何处理
|
||||||
|
|
||||||
// 获取 Header 中的 Authorization
|
// 获取 Header 中的 Authorization
|
||||||
String token = request.getHeaders().getFirst("Authorization");
|
String token = request.getHeaders().getFirst("Authorization");
|
||||||
@@ -39,20 +46,42 @@ public class AuthGlobalFilter implements GlobalFilter, Ordered {
|
|||||||
return exchange.getResponse().setComplete();
|
return exchange.getResponse().setComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// try {
|
// 3. 本地验签 + 解析 claims
|
||||||
// if (!tokenUtils.validateToken(token)) {
|
Jwt jwt;
|
||||||
// log.warn("❌ Token 校验失败: {}", token);
|
try {
|
||||||
// exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
jwt = jwtDecoder.decode(token);
|
||||||
// return exchange.getResponse().setComplete();
|
} catch (JwtValidationException e) {
|
||||||
// }
|
boolean isExpired = e.getErrors().stream()
|
||||||
// } catch (Exception e) {
|
.anyMatch(err -> err.getDescription().contains("expired"));
|
||||||
// log.error("❌ Token 校验异常", e);
|
|
||||||
// exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||||
// return exchange.getResponse().setComplete();
|
if (isExpired) {
|
||||||
// }
|
log.warn("Token 已过期: path={}", path);
|
||||||
|
return exchange.getResponse().setComplete();
|
||||||
|
}
|
||||||
|
log.warn("Token 校验失败: path={}, reason={}", path, e.getMessage());
|
||||||
|
return exchange.getResponse().setComplete();
|
||||||
|
} catch (JwtException e) {
|
||||||
|
log.error("Token解析异常!path:{}", path);
|
||||||
|
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||||
|
return exchange.getResponse().setComplete();
|
||||||
|
}
|
||||||
|
Long userId = (Long) jwt.getClaim("userId");
|
||||||
|
Long tenantId = (Long) jwt.getClaim("tenantId");
|
||||||
|
String username = (String) jwt.getClaim("username");
|
||||||
|
String traceId = UUID.randomUUID().toString();
|
||||||
|
log.info("Token解析结果:userId:{}, tenantId:{}, username:{}", userId, tenantId, username);
|
||||||
|
ServerHttpRequest mutatedRequest = exchange.getRequest()
|
||||||
|
.mutate()
|
||||||
|
.header("X-User-Id", String.valueOf(userId))
|
||||||
|
.header("X-Trace-Id", traceId)
|
||||||
|
.header("X-Tenant-Id", String.valueOf(tenantId))
|
||||||
|
.header("X-Username", username)
|
||||||
|
.headers(h -> h.remove(HttpHeaders.AUTHORIZATION)) // JWT 止步于此
|
||||||
|
.build();
|
||||||
|
|
||||||
log.info("✅ Token 校验通过: {}", token);
|
log.info("✅ Token 校验通过: {}", token);
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange.mutate().request(mutatedRequest).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user