Task 1-3: Mask Sensitive Data trong AdminRequestAspect Logs
Phase: 1 - Security Priority: Medium Module:
adminDepends on: Không có Reference: SPEC.md — xem mục 4 (ADM-F-01 Admin auth riêng) và Code references (admin/aop/AdminRequestAspect.java)
Background
AdminRequestAspect log request body. Nếu có sensitive fields (password, token, coin amount, user personal data), chúng bị log plain text.
Tasks
File: admin/aop/AdminRequestAspect.java
- [ ] Xác nhận hiện tại log những gì (request body? headers?)
-
[ ] Tạo
SensitiveDataMaskerutility:public class SensitiveDataMasker { private static final Set<String> SENSITIVE_KEYS = Set.of( "password", "token", "secret", "coin_amount", "wallet_address", "private_key", "receipt_data" ); public static String mask(String json) { // Replace values for sensitive keys with "***" for (String key : SENSITIVE_KEYS) { json = json.replaceAll( "(?i)(\"" + key + "\"\\s*:\\s*\")[^\"]*\"", "\"" + key + "\": \"***\"" ); } return json; } }Note về package: Đặt
SensitiveDataMaskertrong packageadmin/utils/(ví dụ:com.figpop.admin.utils.SensitiveDataMasker). Đây là plain utility class (không cần@Component), chỉ cần import tĩnh vàoAdminRequestAspect.Edge cases: Regex trên chỉ mask JSON string values (
"key": "value"). Nếu value là number ("coin_amount": 100), cần thêm regex pattern riêng:json = json.replaceAll( "(?i)(\"" + key + "\"\\s*:\\s*)\\d+", "\"" + key + "\": \"***\"" ); -
[ ] Apply trong aspect:
String maskedBody = SensitiveDataMasker.mask(requestBody); LOGGER.info("[ADMIN_AUDIT] admin={} endpoint={} body={}", adminId, endpoint, maskedBody);Note:
adminIdvàendpointcần được lấy từJoinPointhoặcHttpServletRequest. Kiểm tra cáchAdminRequestAspecthiện tại trích xuất thông tin này, đảm bảo không thay đổi logic existing — chỉ thayrequestBodybằngmaskedBodytrong câu lệnh log.
Verification / Acceptance Criteria
- [ ] Code compiles:
AdminRequestAspect.javavàSensitiveDataMasker.javabuild thành công; importSensitiveDataMaskerresolve đúng package - [ ] Password bị mask: Gọi
POST /api/admin/auth/loginvới body{"email":"...", "password":"mySecret"}→ log hiển thị"password": "***", không hiển thị"mySecret" - [ ] Token bị mask: Request body chứa
"token": "abc123"→ log hiển thị"token": "***" - [ ] coin_amount bị mask: Request chứa
"coin_amount": 500→ log hiển thị"coin_amount": "***" - [ ] Non-sensitive fields không bị mask: Các field như
"userId","email"(không trong SENSITIVE_KEYS) vẫn hiển thị nguyên giá trị - [ ] Test class tham khảo:
SensitiveDataMaskerTest(unit test cho utility class) — kiểm tra từng key trongSENSITIVE_KEYSvà các edge cases (numeric values, nested JSON)
Files to Modify
admin/aop/AdminRequestAspect.javaadmin/utils/SensitiveDataMasker.java(new)