Przeglądaj źródła

网关服务-调整过滤器返回方式

sunxbiao 1 rok temu
rodzic
commit
046d3604e1

+ 56 - 18
gateWay_server/src/main/java/com/bjtdba/gateWay/filter/ApiAuthFilter.java

@@ -1,21 +1,26 @@
1
 package com.bjtdba.gateWay.filter;
1
 package com.bjtdba.gateWay.filter;
2
-// ApiAuthFilter.java
2
+
3
 import org.springframework.beans.factory.annotation.Value;
3
 import org.springframework.beans.factory.annotation.Value;
4
 import org.springframework.cloud.gateway.filter.GatewayFilter;
4
 import org.springframework.cloud.gateway.filter.GatewayFilter;
5
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
5
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
6
+import org.springframework.core.io.buffer.DataBuffer;
6
 import org.springframework.http.HttpStatus;
7
 import org.springframework.http.HttpStatus;
8
+import org.springframework.http.MediaType;
7
 import org.springframework.stereotype.Component;
9
 import org.springframework.stereotype.Component;
8
 import org.springframework.util.DigestUtils;
10
 import org.springframework.util.DigestUtils;
9
 import org.springframework.web.server.ServerWebExchange;
11
 import org.springframework.web.server.ServerWebExchange;
10
 import reactor.core.publisher.Mono;
12
 import reactor.core.publisher.Mono;
11
 
13
 
14
+import java.nio.charset.StandardCharsets;
15
+import java.util.HashMap;
16
+import java.util.Map;
17
+
12
 @Component
18
 @Component
13
 public class ApiAuthFilter extends AbstractGatewayFilterFactory<ApiAuthFilter.Config> {
19
 public class ApiAuthFilter extends AbstractGatewayFilterFactory<ApiAuthFilter.Config> {
14
 
20
 
15
     @Value("${external.api.secret}")
21
     @Value("${external.api.secret}")
16
-    private String apiSecret;  // 从配置文件注入密钥
17
-
18
-    private static final long TIMESTAMP_THRESHOLD = 300000;  // 5分钟有效期
22
+    private String apiSecret;
23
+    private static final long TIMESTAMP_THRESHOLD = 300000;
19
 
24
 
20
     public ApiAuthFilter() {
25
     public ApiAuthFilter() {
21
         super(Config.class);
26
         super(Config.class);
@@ -24,47 +29,80 @@ public class ApiAuthFilter extends AbstractGatewayFilterFactory<ApiAuthFilter.Co
24
     @Override
29
     @Override
25
     public GatewayFilter apply(Config config) {
30
     public GatewayFilter apply(Config config) {
26
         return (exchange, chain) -> {
31
         return (exchange, chain) -> {
27
-            // 仅处理/external路径的请求
28
             if (!exchange.getRequest().getPath().value().startsWith("/external")) {
32
             if (!exchange.getRequest().getPath().value().startsWith("/external")) {
29
                 return chain.filter(exchange);
33
                 return chain.filter(exchange);
30
             }
34
             }
31
 
35
 
32
-            // 1. 获取认证头信息
33
             String apiKey = exchange.getRequest().getHeaders().getFirst("X-API-KEY");
36
             String apiKey = exchange.getRequest().getHeaders().getFirst("X-API-KEY");
34
             String timestamp = exchange.getRequest().getHeaders().getFirst("X-TIMESTAMP");
37
             String timestamp = exchange.getRequest().getHeaders().getFirst("X-TIMESTAMP");
35
             String signature = exchange.getRequest().getHeaders().getFirst("X-SIGNATURE");
38
             String signature = exchange.getRequest().getHeaders().getFirst("X-SIGNATURE");
36
 
39
 
37
-            // 2. 验证必要头信息存在
38
             if (apiKey == null || timestamp == null || signature == null) {
40
             if (apiKey == null || timestamp == null || signature == null) {
39
-                return unauthorized(exchange, "Missing authentication headers");
41
+                return createErrorResponse(exchange, 401, "Missing authentication headers", HttpStatus.UNAUTHORIZED);
40
             }
42
             }
41
 
43
 
42
-            // 3. 验证时间戳有效性
43
             try {
44
             try {
44
                 long requestTime = Long.parseLong(timestamp);
45
                 long requestTime = Long.parseLong(timestamp);
45
                 long currentTime = System.currentTimeMillis();
46
                 long currentTime = System.currentTimeMillis();
46
 
47
 
47
                 if (Math.abs(currentTime - requestTime) > TIMESTAMP_THRESHOLD) {
48
                 if (Math.abs(currentTime - requestTime) > TIMESTAMP_THRESHOLD) {
48
-                    return unauthorized(exchange, "Timestamp expired");
49
+                    return createErrorResponse(exchange, 401, "Timestamp expired", HttpStatus.UNAUTHORIZED);
49
                 }
50
                 }
50
             } catch (NumberFormatException e) {
51
             } catch (NumberFormatException e) {
51
-                return unauthorized(exchange, "Invalid timestamp format");
52
+                return createErrorResponse(exchange, 400, "Invalid timestamp format", HttpStatus.BAD_REQUEST);
52
             }
53
             }
53
 
54
 
54
-            // 4. 生成并验证签名
55
             String expectedSignature = generateSignature(apiKey, timestamp);
55
             String expectedSignature = generateSignature(apiKey, timestamp);
56
             if (!expectedSignature.equalsIgnoreCase(signature)) {
56
             if (!expectedSignature.equalsIgnoreCase(signature)) {
57
-                return unauthorized(exchange, "Invalid signature");
57
+                return createErrorResponse(exchange, 401, "Invalid signature", HttpStatus.UNAUTHORIZED);
58
             }
58
             }
59
-            System.out.println("Forwarding to: " + exchange.getRequest().getURI());
59
+
60
             return chain.filter(exchange);
60
             return chain.filter(exchange);
61
         };
61
         };
62
     }
62
     }
63
 
63
 
64
-    private Mono<Void> unauthorized(ServerWebExchange exchange, String reason) {
65
-        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
66
-        exchange.getResponse().getHeaders().add("X-Auth-Error", reason);
67
-        return exchange.getResponse().setComplete();
64
+    /**
65
+     * 创建标准错误响应
66
+     *
67
+     * @param exchange 请求上下文
68
+     * @param code 业务错误码
69
+     * @param message 错误消息
70
+     * @param httpStatus HTTP状态码
71
+     * @return Mono<Void>
72
+     */
73
+    private Mono<Void> createErrorResponse(ServerWebExchange exchange, int code,
74
+                                           String message, HttpStatus httpStatus) {
75
+        exchange.getResponse().setStatusCode(httpStatus);
76
+        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
77
+
78
+        // 构建标准响应格式
79
+        Map<String, Object> responseMap = new HashMap<>();
80
+        responseMap.put("code", code);
81
+        responseMap.put("message", message);
82
+        responseMap.put("data", null);
83
+
84
+        // 手动序列化JSON
85
+        String jsonResponse = "{\"code\":" + code +
86
+                ",\"message\":\"" + escapeJson(message) +
87
+                "\",\"data\":null}";
88
+
89
+        byte[] bytes = jsonResponse.getBytes(StandardCharsets.UTF_8);
90
+        DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
91
+
92
+        return exchange.getResponse().writeWith(Mono.just(buffer));
93
+    }
94
+
95
+    /**
96
+     * 转义JSON字符串中的特殊字符
97
+     */
98
+    private String escapeJson(String input) {
99
+        return input.replace("\"", "\\\"")
100
+                .replace("\\", "\\\\")
101
+                .replace("\b", "\\b")
102
+                .replace("\f", "\\f")
103
+                .replace("\n", "\\n")
104
+                .replace("\r", "\\r")
105
+                .replace("\t", "\\t");
68
     }
106
     }
69
 
107
 
70
     private String generateSignature(String apiKey, String timestamp) {
108
     private String generateSignature(String apiKey, String timestamp) {