|
|
@@ -0,0 +1,176 @@
|
|
|
+package com.malk.utils;
|
|
|
+
|
|
|
+import org.junit.Test;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.LinkedHashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import static org.junit.Assert.assertEquals;
|
|
|
+import static org.junit.Assert.assertFalse;
|
|
|
+import static org.junit.Assert.assertNull;
|
|
|
+import static org.junit.Assert.assertTrue;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 单元测试:{@link UtilHttpAudit}
|
|
|
+ *
|
|
|
+ * <p>覆盖 sanitize 脱敏规则 / endpoint URL 解析 / vendor 识别。
|
|
|
+ * BACKLOG B2.1 + mjava-baseline §3.5 审计日志能力。</p>
|
|
|
+ */
|
|
|
+public class UtilHttpAuditTest {
|
|
|
+
|
|
|
+ // ---------- sanitize ----------
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_null_returns_null() {
|
|
|
+ assertNull(UtilHttpAudit.sanitize(null));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_empty_returns_empty() {
|
|
|
+ assertTrue(UtilHttpAudit.sanitize(new HashMap<>()).isEmpty());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_token_field_masked() {
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("access_token", "abc123");
|
|
|
+ in.put("name", "alice");
|
|
|
+ Map<String, Object> out = UtilHttpAudit.sanitize(in);
|
|
|
+ assertEquals("***", out.get("access_token"));
|
|
|
+ assertEquals("alice", out.get("name"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_appSecret_password_aesKey_privateKey_all_masked() {
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("appSecret", "s1");
|
|
|
+ in.put("password", "p1");
|
|
|
+ in.put("aesKey", "k1");
|
|
|
+ in.put("privateKey", "k2");
|
|
|
+ in.put("clientSecret", "s2");
|
|
|
+ in.put("safeField", "ok");
|
|
|
+ Map<String, Object> out = UtilHttpAudit.sanitize(in);
|
|
|
+ assertEquals("***", out.get("appSecret"));
|
|
|
+ assertEquals("***", out.get("password"));
|
|
|
+ assertEquals("***", out.get("aesKey"));
|
|
|
+ assertEquals("***", out.get("privateKey"));
|
|
|
+ assertEquals("***", out.get("clientSecret"));
|
|
|
+ assertEquals("ok", out.get("safeField"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_case_insensitive() {
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("ACCESS_TOKEN", "x");
|
|
|
+ in.put("Password", "y");
|
|
|
+ in.put("appSECRET", "z");
|
|
|
+ Map<String, Object> out = UtilHttpAudit.sanitize(in);
|
|
|
+ assertEquals("***", out.get("ACCESS_TOKEN"));
|
|
|
+ assertEquals("***", out.get("Password"));
|
|
|
+ assertEquals("***", out.get("appSECRET"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_recurses_into_nested_map() {
|
|
|
+ Map<String, Object> inner = new LinkedHashMap<>();
|
|
|
+ inner.put("token", "secret-val");
|
|
|
+ inner.put("desc", "ok");
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("config", inner);
|
|
|
+ in.put("name", "alice");
|
|
|
+
|
|
|
+ Map<String, Object> out = UtilHttpAudit.sanitize(in);
|
|
|
+ Map<String, Object> outInner = (Map<String, Object>) out.get("config");
|
|
|
+ assertEquals("***", outInner.get("token"));
|
|
|
+ assertEquals("ok", outInner.get("desc"));
|
|
|
+ assertEquals("alice", out.get("name"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_preserves_non_sensitive_values() {
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("count", 42);
|
|
|
+ in.put("active", true);
|
|
|
+ in.put("tags", Arrays.asList("a", "b"));
|
|
|
+ Map<String, Object> out = UtilHttpAudit.sanitize(in);
|
|
|
+ assertEquals(42, out.get("count"));
|
|
|
+ assertEquals(true, out.get("active"));
|
|
|
+ assertEquals(Arrays.asList("a", "b"), out.get("tags"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void sanitize_does_not_mutate_input() {
|
|
|
+ Map<String, Object> in = new HashMap<>();
|
|
|
+ in.put("token", "raw");
|
|
|
+ UtilHttpAudit.sanitize(in);
|
|
|
+ assertEquals("源 Map 不应被改写", "raw", in.get("token"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------- isSensitiveKey ----------
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void isSensitiveKey_null_or_empty_returns_false() {
|
|
|
+ assertFalse(UtilHttpAudit.isSensitiveKey(null));
|
|
|
+ assertFalse(UtilHttpAudit.isSensitiveKey(""));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void isSensitiveKey_safe_keys_return_false() {
|
|
|
+ assertFalse(UtilHttpAudit.isSensitiveKey("name"));
|
|
|
+ assertFalse(UtilHttpAudit.isSensitiveKey("user_id"));
|
|
|
+ assertFalse(UtilHttpAudit.isSensitiveKey("dept_id_list"));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------- endpoint ----------
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void endpoint_full_url_extracts_path() {
|
|
|
+ assertEquals("/v1.0/yida/forms/instances",
|
|
|
+ UtilHttpAudit.endpoint("https://api.dingtalk.com/v1.0/yida/forms/instances"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void endpoint_strips_query_string() {
|
|
|
+ assertEquals("/topapi/v2/user/get",
|
|
|
+ UtilHttpAudit.endpoint("https://oapi.dingtalk.com/topapi/v2/user/get?access_token=xxx"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void endpoint_no_path_returns_slash() {
|
|
|
+ assertEquals("/", UtilHttpAudit.endpoint("https://api.example.com"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void endpoint_relative_url_returns_as_is() {
|
|
|
+ assertEquals("/iam/api/users", UtilHttpAudit.endpoint("/iam/api/users"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void endpoint_null_or_empty_returns_empty() {
|
|
|
+ assertEquals("", UtilHttpAudit.endpoint(null));
|
|
|
+ assertEquals("", UtilHttpAudit.endpoint(""));
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------- vendor ----------
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void vendor_dingtalk_recognized() {
|
|
|
+ assertEquals("dingtalk", UtilHttpAudit.vendor("https://oapi.dingtalk.com/gettoken"));
|
|
|
+ assertEquals("dingtalk", UtilHttpAudit.vendor("https://api.dingtalk.com/v1.0/yida/forms/instances"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void vendor_other_vendors_recognized() {
|
|
|
+ assertEquals("fxiaoke", UtilHttpAudit.vendor("https://open.fxiaoke.com/cgi/user/getByMobile"));
|
|
|
+ assertEquals("teambition", UtilHttpAudit.vendor("https://open.teambition.com/api/v3/project/query"));
|
|
|
+ assertEquals("feishu", UtilHttpAudit.vendor("https://open.feishu.cn/open-apis/auth"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ public void vendor_unknown_returns_other() {
|
|
|
+ assertEquals("other", UtilHttpAudit.vendor("https://example.com/api"));
|
|
|
+ assertEquals("other", UtilHttpAudit.vendor(null));
|
|
|
+ }
|
|
|
+}
|