c# - 记录具有保存敏感数据(待散列)属性的对象

标签 c# .net logging .net-4.0 log4net

上下文

我正在设计应用程序的日志记录功能。
寻找一个优雅且性能良好的解决方案。
(当然我不会重新实现轮子 :)。我将使用流行的日志记录库——例如 Nlog、Serilog……)。

要求

记录可能包含具有敏感信息属性的对象
让我们假设一个类人:

class Person {
    string Name { get; set; }
    string SensitiveInfo { get; set; }
}

一个不好的(在我看来)方法是做这样的事情:

logger.Debug($"{person.Name}, {Hash(person.SenstiveInfo)}");

为什么我觉得这不好?

  1. 这是一个调试日志,可能永远不会记录(基于日志记录级别)。因此,它正在浪费 CPU 资源来进行不必要的散列。
  2. 我更愿意允许对象按原样传递(例如:logger.Debug(person) ),而不是强制开发人员手动分解所有对象属性。

到目前为止的想法...

以下两种方法都需要一个 loggerWrapper,如果可能的话,我想避免:

class LoggerWrapper {
    LoggerWrapper (ILogger logger) {
        //store the ILogger
    }
    void Log(object objectToBeLogged, LoggingLevel level) {
        //If logging level is not accepted return
        _logger.Log(objectToBeLogged, level);
    }
}

<强>1。创建一个 ILoggable 接口(interface)

interface ILoggable {
    string GetLogValue(HashManager hashManager);
}

class Person: ILoggable {
    string Name { get; set; }
    string SensitiveInfo { get; set; }

    string GetLogValue(HashManager hashManager) {
        string hashedValue = hashManager.Hash(person.SenstiveInfo);
        return $"{person.Name}, {hashedValue}"
    }
}

// Now the LogWrapper.Log will expect an ILoggable, and will use the 'GetLogValue' method
// overriding 'ToString()' is an alternative but it is exposed by the 'object' class, and i fear that is not strict enough/can be forgotten.

对这种方法的担忧:对开发人员的要求太高?可维护性?

<强>2。注解与反射

class Person {
    [Loggable]
    string Name { get; set; }
    [Loggable, SensitiveInfo]
    string SensitiveInfo { get; set; }
}

// Now the logWrapper will rely on reflection (i think) and choose what to log/hash

担心这种方法:性能?


上述方法是否被视为不良做法? 有没有更好的方法?
是否有任何图书馆已经在处理这个问题?

最佳答案

您的第二种方法没问题。

我可以想到几种替代方法,但它们最终会非常接近您所拥有的属性注释。
- 比如在外部文件中保留某种注释信息。
- 或创建特殊类型,如 ' SensitiveInfo<T> ' 并在必须进行散列的地方使用它,但几乎与注释属性相同。

对于性能部分:
您可以在应用程序开始时创建一次结构,该结构扫描程序集中的所有类型。该结构可以是具有类型名称作为键("MyCompany.App.Core.Person")的字典,对于值,您可以使用 Func 。从 dynamically compiled lambda expression 创建的对象这将在需要时返回带有散列值的日志消息。 (这将是困难的部分)。
重要说明: jit 编译器在需要之前不会加载 dll,因此尝试在启动开始时创建此结构可以跳过一些程序集。作为替代方法,您可以尝试按需(惰性)填充结构作为记录器包装器的一部分。

然后我将使用日志包装器,它将使用该结构为特定对象创建日志消息。

一些建议:
1. 记录太多信息不一定是坏事 - 所以我不会使用 [ Loggable ] 属性 - 只记录对象中的所有内容。这样开发人员的开销就会最小。有时你的对象中可能有很长的字符串,这些字符串并不重要,那么你可以引入 [ NonLoggable ]属性。
2. 您可能会处理层次结构对象 - 这会增加创建 func/labbda 表达式的额外复杂性。

总体而言,这种方法更复杂,但对开发人员的要求较低。
最后,这取决于您和您的团队愿意做什么以及将花费/节省的工作量(这将取决于项目的大小......等)。


我认为第一种方法将难以维护并且会增加很多噪音。日志记录应该是基础架构关注点 - 尽可能自动化。

关于c# - 记录具有保存敏感数据(待散列)属性的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58670397/

相关文章:

java - 如何安静 Drools 资源扫描仪日志记录?

logging - 如何在 Akka.NET 中禁用集群心跳日志记录

c# - WPF:如果加载事件中发生异常,应用程序不会崩溃

C# - 存储用户密码以供比较

c# - 使用 xml 作为配置文件

c# - finally block 的隐藏功能?

.net - 使用 Windows 窗体作为抽象类 - 使用哪种模式?

c# - c#中 boolean 值的二进制表示是什么

c# - 如何编写一个 C# 方法来接受未知类型的注入(inject)依赖项?

java - log4j2 健康信息和错误处理