刘帅
2026-09-17 12732229b53d2280074cea3f91f3aa67b578ac7f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.dsh.guns.modular.system.audit;
 
import com.dsh.guns.config.UserExt;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
 
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
/** Spring 会把该 RequestInterceptor 应用于管理端全部 Feign 客户端。 */
@Component
public class ManagementFeignAuditInterceptor implements RequestInterceptor {
    @Resource private ManagementAuditWriter auditWriter;
 
    @Override
    public void apply(RequestTemplate template) {
        try {
            Map<String, Object> audit = new HashMap<String, Object>();
            String url = template.url();
            if (url != null && url.startsWith("/internal/sensitive/")
                    && UserExt.getUser() != null && "admin".equalsIgnoreCase(UserExt.getUser().getAccount())) {
                template.header("X-Internal-Sensitive-Access", "true");
            }
            audit.put("traceId", UUID.randomUUID().toString().replace("-", ""));
            audit.put("sourceService", "mb-cloud-management");
            audit.put("sourceType", "FEIGN");
            audit.put("operationType", "FEIGN_CALL");
            audit.put("riskLevel", riskLevel(url));
            audit.put("operationName", template.feignTarget() == null ? "Feign调用" : template.feignTarget().name());
            audit.put("requestMethod", template.method());
            audit.put("requestUri", url);
            audit.put("requestParams", template.body() == null ? null : "bodyBytes=" + template.body().length);
            audit.put("userId", UserExt.getUser() == null ? null : UserExt.getUser().getId());
            audit.put("userAccount", UserExt.getUser() == null ? null : UserExt.getUser().getAccount());
            audit.put("result", "REQUESTED");
            audit.put("createdAt", new Date());
            auditWriter.append(audit);
        } catch (Exception ignored) {
            // 审计异常绝不能阻塞原 Feign 调用。
        }
    }
 
    private String riskLevel(String url) {
        String value = url == null ? "" : url.toLowerCase();
        return value.matches(".*(ticket|payment|finance|refund|withdraw|balance|status|state).*") ? "CRITICAL" : "NORMAL";
    }
}