Android日志密码混淆:String.replaceAll在部分设备上失效
解决方案:Android日志中混淆明文密码
针对你遇到的这个需求——在调试日志里自动掩盖API请求中的明文密码,我整理了一套可靠的实现方案,既能处理普通JSON结构,也能覆盖嵌套的对象和数组,确保所有敏感密码都不会泄露在日志中。
核心思路
- 预先定义所有需要混淆的密码字段名(比如
password、pwd这类常见字段) - 递归解析JSON结构,遍历所有层级的字段内容
- 匹配到目标字段后,将明文替换为混淆字符串(比如
***) - 兼容JSONObject和JSONArray两种格式,非合法JSON直接返回原内容避免日志报错
完整代码实现
import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class LogUtils { // 可自定义:添加所有需要混淆的密码相关字段名 private static final String[] PASSWORD_FIELDS = {"password", "pwd", "login_pwd", "user_password"}; /** * 混淆JSON字符串中的所有明文密码字段 * @param jsonStr 原始JSON请求字符串 * @return 混淆后的安全字符串 */ public static String obfuscatePasswordInJson(String jsonStr) { try { // 先尝试解析为JSONObject JSONObject jsonObject = new JSONObject(jsonStr); obfuscatePasswordFields(jsonObject); return jsonObject.toString(); } catch (JSONException e) { try { // 如果是JSONArray格式 JSONArray jsonArray = new JSONArray(jsonStr); obfuscatePasswordInArray(jsonArray); return jsonArray.toString(); } catch (JSONException ex) { // 不是合法JSON,直接返回原字符串 return jsonStr; } } } // 处理JSONObject中的密码字段 private static void obfuscatePasswordFields(JSONObject jsonObject) throws JSONException { // 替换当前层级的密码字段 for (String field : PASSWORD_FIELDS) { if (jsonObject.has(field)) { jsonObject.put(field, "***"); } } // 递归处理嵌套的JSONObject或JSONArray for (String key : jsonObject.keySet()) { Object value = jsonObject.get(key); if (value instanceof JSONObject) { obfuscatePasswordFields((JSONObject) value); } else if (value instanceof JSONArray) { obfuscatePasswordInArray((JSONArray) value); } } } // 处理JSONArray中的密码字段 private static void obfuscatePasswordInArray(JSONArray jsonArray) throws JSONException { for (int i = 0; i < jsonArray.length(); i++) { Object item = jsonArray.get(i); if (item instanceof JSONObject) { obfuscatePasswordFields((JSONObject) item); } else if (item instanceof JSONArray) { obfuscatePasswordInArray((JSONArray) item); } } } // 可选:自定义混淆规则(比如保留前2位,其余替换为***) private static String customMaskPassword(String rawPassword) { if (rawPassword == null || rawPassword.length() <= 2) { return "***"; } return rawPassword.substring(0, 2) + "***"; } }
使用示例
在你输出请求日志的地方,只需要把原始JSON字符串传入工具方法即可:
// 假设你的请求JSON字符串是requestJson String safeLogContent = LogUtils.obfuscatePasswordInJson(requestJson); // 输出混淆后的安全日志 Log.d("AppDebug", "API Request: " + safeLogContent);
额外建议
- 如果你使用第三方日志框架(比如Timber),可以把这个混淆逻辑集成到自定义日志树里,这样所有包含JSON的日志都会自动处理,不用每次手动调用
- 根据对接API的实际字段名,更新
PASSWORD_FIELDS数组,确保不会遗漏任何密码字段 - 如果需要更灵活的混淆规则,比如保留部分字符,可以替换代码中的
"***"为customMaskPassword(jsonObject.getString(field)),使用自定义的混淆方法
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

