买家端需要的获取商家主页和模糊搜索接口
This commit is contained in:
@@ -19,5 +19,13 @@ public class GatewayAuthProperties {
|
|||||||
|
|
||||||
private List<String> ignorePaths;
|
private List<String> ignorePaths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 可选认证路径:token 有则解析并写入下游请求头,无则放行。
|
||||||
|
* 与 ignorePaths 的区别:ignorePaths 完全跳过认证逻辑;
|
||||||
|
* optionalAuthPaths 仍然尝试解析 token,有 token 时正常写入 X-User-Id / X-User-Info,
|
||||||
|
* 无 token 时才放行,确保已登录用户的信息能正确传递。
|
||||||
|
*/
|
||||||
|
private List<String> optionalAuthPaths;
|
||||||
|
|
||||||
private boolean blacklistEnabled = true;
|
private boolean blacklistEnabled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,24 +65,43 @@ public class GlobalAuthWebFilter implements WebFilter, Ordered {
|
|||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 白名单直接放行
|
// 2. 白名单直接放行(完全跳过认证)
|
||||||
if (isIgnoredPath(path)) {
|
if (isIgnoredPath(path)) {
|
||||||
return chain.filter(exchange);
|
return chain.filter(exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 提取 token
|
// 3. 可选认证路径:token 有则解析,无则放行
|
||||||
|
if (isOptionalAuthPath(path)) {
|
||||||
|
String rawHeader = exchange.getRequest().getHeaders()
|
||||||
|
.getFirst(authProperties.getJwtTokenHeader());
|
||||||
|
if (StrUtil.isBlank(rawHeader)) {
|
||||||
|
// 无 token,直接放行,不写任何 header
|
||||||
|
return chain.filter(exchange);
|
||||||
|
}
|
||||||
|
// 有 token,正常走解析流程(复用下面的验证逻辑)
|
||||||
|
return processTokenWithAuthCheck(exchange, chain, rawHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 其他路径:必须有 token
|
||||||
String rawHeader = exchange.getRequest().getHeaders()
|
String rawHeader = exchange.getRequest().getHeaders()
|
||||||
.getFirst(authProperties.getJwtTokenHeader());
|
.getFirst(authProperties.getJwtTokenHeader());
|
||||||
if (StrUtil.isBlank(rawHeader)) {
|
if (StrUtil.isBlank(rawHeader)) {
|
||||||
return writeUnauthorized(exchange, AuthConstants.MSG_MISSING_TOKEN);
|
return writeUnauthorized(exchange, AuthConstants.MSG_MISSING_TOKEN);
|
||||||
}
|
}
|
||||||
|
return processTokenWithAuthCheck(exchange, chain, rawHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一的 token 解析与认证流程:解析 JWT → 黑名单检查 → 写入下游 header。
|
||||||
|
* 专供可选认证路径中有 token 的情况,以及普通路径的鉴权。
|
||||||
|
*/
|
||||||
|
private Mono<Void> processTokenWithAuthCheck(ServerWebExchange exchange, WebFilterChain chain, String rawHeader) {
|
||||||
String token = rawHeader;
|
String token = rawHeader;
|
||||||
if (rawHeader.startsWith(authProperties.getJwtTokenPrefix())) {
|
if (rawHeader.startsWith(authProperties.getJwtTokenPrefix())) {
|
||||||
token = rawHeader.substring(authProperties.getJwtTokenPrefix().length());
|
token = rawHeader.substring(authProperties.getJwtTokenPrefix().length());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. JWT 签名验证
|
// JWT 签名验证
|
||||||
Claims claims;
|
Claims claims;
|
||||||
try {
|
try {
|
||||||
claims = parseToken(token);
|
claims = parseToken(token);
|
||||||
@@ -91,7 +110,7 @@ public class GlobalAuthWebFilter implements WebFilter, Ordered {
|
|||||||
return writeUnauthorized(exchange, AuthConstants.MSG_TOKEN_EXPIRED);
|
return writeUnauthorized(exchange, AuthConstants.MSG_TOKEN_EXPIRED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 解析用户信息
|
// 解析用户信息
|
||||||
AuthPrincipalVo principal;
|
AuthPrincipalVo principal;
|
||||||
try {
|
try {
|
||||||
principal = objectMapper.readValue(claims.getSubject(), AuthPrincipalVo.class);
|
principal = objectMapper.readValue(claims.getSubject(), AuthPrincipalVo.class);
|
||||||
@@ -104,7 +123,7 @@ public class GlobalAuthWebFilter implements WebFilter, Ordered {
|
|||||||
return writeUnauthorized(exchange, AuthConstants.MSG_INVALID_TOKEN);
|
return writeUnauthorized(exchange, AuthConstants.MSG_INVALID_TOKEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 黑名单检查(仅当启用时)
|
// 黑名单检查
|
||||||
if (authProperties.isBlacklistEnabled()) {
|
if (authProperties.isBlacklistEnabled()) {
|
||||||
String blacklistKey = AuthConstants.BLACKLIST_PREFIX + principal.getId();
|
String blacklistKey = AuthConstants.BLACKLIST_PREFIX + principal.getId();
|
||||||
return redisTemplate.hasKey(blacklistKey).flatMap(isBlacklisted -> {
|
return redisTemplate.hasKey(blacklistKey).flatMap(isBlacklisted -> {
|
||||||
@@ -151,6 +170,18 @@ public class GlobalAuthWebFilter implements WebFilter, Ordered {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isOptionalAuthPath(String requestUri) {
|
||||||
|
if (authProperties.getOptionalAuthPaths() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String pattern : authProperties.getOptionalAuthPaths()) {
|
||||||
|
if (pathMatcher.match(pattern, requestUri)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private Claims parseToken(String token) {
|
private Claims parseToken(String token) {
|
||||||
SecretKey key = buildSigningKey();
|
SecretKey key = buildSigningKey();
|
||||||
return Jwts.parser()
|
return Jwts.parser()
|
||||||
|
|||||||
@@ -75,6 +75,9 @@ gateway:
|
|||||||
jwt-token-header: Authorization
|
jwt-token-header: Authorization
|
||||||
jwt-token-prefix: Bearer-
|
jwt-token-prefix: Bearer-
|
||||||
blacklist-enabled: true
|
blacklist-enabled: true
|
||||||
|
# 可选认证路径:token 有则解析并传递,无则放行(已登录用户身份仍能正确传递)
|
||||||
|
optional-auth-paths:
|
||||||
|
- /seller/listing/shop
|
||||||
ignore-paths:
|
ignore-paths:
|
||||||
# Static resources & docs
|
# Static resources & docs
|
||||||
- /favicon.ico
|
- /favicon.ico
|
||||||
@@ -108,6 +111,7 @@ gateway:
|
|||||||
- /gateway/healthy
|
- /gateway/healthy
|
||||||
# Designer
|
# Designer
|
||||||
- /aida/api/designer/check
|
- /aida/api/designer/check
|
||||||
|
- /seller/designer/shop/**
|
||||||
# Python (only /aida prefix)
|
# Python (only /aida prefix)
|
||||||
- /aida/api/python/saveGeneratePicture
|
- /aida/api/python/saveGeneratePicture
|
||||||
- /aida/api/python/getLibraryByUserId
|
- /aida/api/python/getLibraryByUserId
|
||||||
|
|||||||
Reference in New Issue
Block a user