如何在JSON中屏蔽敏感值以进行日志记录

时间:2016-06-14 20:15:25

标签: json json.net

我有几个类似的JSON结构,我想写入SQL表以进行日志记录。但是,JSON中的某些字段包含敏感信息,我想部分屏蔽这些信息,因此在日志中看不到完整值。

以下是其中一个JSON结构的示例:

{
  "Vault": 1,
  "Transaction": {
    "gateway": {
      "Login": "Nick",
      "Password": "Password"
    },
    "credit_card": {
      "number": "4111111111111"
    }
  }
}

在这种情况下,我尝试更改4111信用卡号,使其在JSON中显示为4xxx1111。我正在使用Newtonsoft并将JSON反序列化为JObject,但我仍然坚持如何掩盖该值。我认为线索与JToken有关,但还没有想到它。我想使解决方案尽可能通用,以便它可以与我可能需要注销的任何JSON结构一起使用。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:5)

以下是我认为我会采取的方法:

  1. 创建一个可以获取字符串值的辅助方法,并以您日志所需的方式隐藏它。也许是这样的,例如:

    SCOPES = [ 'openid', 'profile', 'offline_access', 'https://outlook.office.com/mail.read' ]
  2. 制作另一个可以接受public static string Obscure(string s) { if (string.IsNullOrEmpty(s)) return s; int len = s.Length; int leftLen = len > 4 ? 1 : 0; int rightLen = len > 6 ? Math.Min((len - 6) / 2, 4) : 0; return s.Substring(0, leftLen) + new string('*', len - leftLen - rightLen) + s.Substring(len - rightLen); } JSONPath表达式列表的辅助方法。在此方法中,使用JToken将每个路径与令牌的内容进行匹配。对于找到的每个匹配项,请使用第一个帮助程序方法将敏感值替换为模糊版本。

    SelectTokens
  3. 最后,编译一个JSONPath表达式列表,列出您希望在预期获得的所有JSON主体中隐藏的值。从您上面的示例JSON开始,我认为您希望隐藏public static void ObscureMatchingValues(JToken token, IEnumerable<string> jsonPaths) { foreach (string path in jsonPaths) { foreach (JToken match in token.SelectTokens(path)) { match.Replace(new JValue(Obscure(match.ToString()))); } } } 无论发生在哪里,Password如果它出现在number内。表示为JSONPath,分别为credit_card$..Password。 (请记住,JSON.Net中的JSONPath表达式区分大小写。)获取此列表并将其放入某个配置设置中,以便在需要时可以轻松更改。

  4. 现在,只要你想注销一些JSON,就这样做:

    $..credit_card.number
  5. 演示小提琴:https://dotnetfiddle.net/dGPyJF

答案 1 :(得分:2)

您可以使用 Json Converter 来转换特定的命名属性以进行屏蔽。这是一个例子:

public class KeysJsonConverter : JsonConverter
{
private readonly Type[] _types;
private readonly string[] _pinValues= new[] { "number","Password" };

public KeysJsonConverter(params Type[] types)
{
    _types = types;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    JToken t = JToken.FromObject(value);

        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
        }
        else
        {
            JObject o = (JObject)t;
            IList<JProperty> propertyNames = o.Properties().Where(p => _pinValues.Contains(p.Name)).ToList();

            foreach (var property in propertyNames)
            {
                string propertyValue = (string)property.Value;
                property.Value = propertyValue?.Length > 2 ? propertyValue.Substring(0, 2).PadRight(propertyValue.Length, '*') : "Invalid Value";
            }
            o.WriteTo(writer);
        }
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    throw new NotImplementedException();
}

public override bool CanRead
{
    get { return false; }
}

public override bool CanConvert(Type objectType)
{
    return _types.Any(t => t == objectType);
}  

}

然后将 Json 称为:JsonConvert.SerializeObject(Result, new KeysJsonConverter(typeof(Method)))