跳过内容

MASTG-BEST-0002: 移除日志代码

理想情况下,发布版本不应使用任何日志记录功能,从而更容易评估敏感数据泄露。

使用 ProGuard

在准备生产版本时,您可以使用诸如 Proguard (包含在 Android Studio 中)的工具。要确定是否已删除 android.util.Log 类中的所有日志记录功能,请检查 ProGuard 配置文件 (proguard-rules.pro) 中是否包含以下选项(根据此移除日志代码的 ProGuard 示例和此关于在 Android Studio 项目中启用 ProGuard的文章)

-assumenosideeffects class android.util.Log
{
  public static boolean isLoggable(java.lang.String, int);
  public static int v(...);
  public static int i(...);
  public static int w(...);
  public static int d(...);
  public static int e(...);
  public static int wtf(...);
}

请注意,上面的示例仅确保删除对 Log 类方法的调用。 如果要记录的字符串是动态构建的,则构建字符串的代码可能仍保留在字节码中。 例如,以下代码发出一个隐式的 StringBuilder 来构造日志语句

Java 示例

Log.v("Private key tag", "Private key [byte format]: " + key);

Kotlin 示例

Log.v("Private key tag", "Private key [byte format]: $key")

但是,编译后的字节码等效于以下日志语句的字节码,该日志语句显式构造字符串

Java 示例

Log.v("Private key tag", new StringBuilder("Private key [byte format]: ").append(key.toString()).toString());

Kotlin 示例

Log.v("Private key tag", StringBuilder("Private key [byte format]: ").append(key).toString())

ProGuard 保证删除 Log.v 方法调用。 其余代码 (new StringBuilder ...) 是否会被删除取决于代码的复杂性和 ProGuard 版本

这是一个安全风险,因为(未使用的)字符串会将纯文本数据泄漏到内存中,可以通过调试器或内存转储来访问这些数据。

不幸的是,没有解决此问题的万能方法,但一种选择是实现一个自定义日志记录工具,该工具接受简单的参数并在内部构造日志语句。

SecureLog.v("Private key [byte format]: ", key);

然后配置 ProGuard 以剥离其调用。

自定义日志

您可以实现一个自定义日志记录工具,并且仅针对发布版本一次性禁用它。

测试

MASTG-TEST-0231:对日志记录 API 的引用 MASTG-TEST-0203:日志记录 API 的运行时使用