Pārlūkot izejas kodu

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

sunxbiao 1 gadu atpakaļ
vecāks
revīzija
046d3604e1

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

@@ -1,21 +1,26 @@
1 1
 package com.bjtdba.gateWay.filter;
2
-// ApiAuthFilter.java
2
+
3 3
 import org.springframework.beans.factory.annotation.Value;
4 4
 import org.springframework.cloud.gateway.filter.GatewayFilter;
5 5
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
6
+import org.springframework.core.io.buffer.DataBuffer;
6 7
 import org.springframework.http.HttpStatus;
8
+import org.springframework.http.MediaType;
7 9
 import org.springframework.stereotype.Component;
8 10
 import org.springframework.util.DigestUtils;
9 11
 import org.springframework.web.server.ServerWebExchange;
10 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 18
 @Component
13 19
 public class ApiAuthFilter extends AbstractGatewayFilterFactory<ApiAuthFilter.Config> {
14 20
 
15 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 25
     public ApiAuthFilter() {
21 26
         super(Config.class);
@@ -24,47 +29,80 @@ public class ApiAuthFilter extends AbstractGatewayFilterFactory<ApiAuthFilter.Co
24 29
     @Override
25 30
     public GatewayFilter apply(Config config) {
26 31
         return (exchange, chain) -> {
27
-            // 仅处理/external路径的请求
28 32
             if (!exchange.getRequest().getPath().value().startsWith("/external")) {
29 33
                 return chain.filter(exchange);
30 34
             }
31 35
 
32
-            // 1. 获取认证头信息
33 36
             String apiKey = exchange.getRequest().getHeaders().getFirst("X-API-KEY");
34 37
             String timestamp = exchange.getRequest().getHeaders().getFirst("X-TIMESTAMP");
35 38
             String signature = exchange.getRequest().getHeaders().getFirst("X-SIGNATURE");
36 39
 
37
-            // 2. 验证必要头信息存在
38 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 44
             try {
44 45
                 long requestTime = Long.parseLong(timestamp);
45 46
                 long currentTime = System.currentTimeMillis();
46 47
 
47 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 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 55
             String expectedSignature = generateSignature(apiKey, timestamp);
56 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 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 108
     private String generateSignature(String apiKey, String timestamp) {