我有几个类似的JSON结构,我想写入SQL表以进行日志记录。但是,JSON中的某些字段包含敏感信息,我想部分屏蔽这些信息,因此在日志中看不到完整值。
以下是其中一个JSON结构的示例:
{
"Vault": 1,
"Transaction": {
"gateway": {
"Login": "Nick",
"Password": "Password"
},
"credit_card": {
"number": "4111111111111"
}
}
}
在这种情况下,我尝试更改4111
信用卡号,使其在JSON中显示为4xxx1111
。我正在使用Newtonsoft并将JSON反序列化为JObject
,但我仍然坚持如何掩盖该值。我认为线索与JToken
有关,但还没有想到它。我想使解决方案尽可能通用,以便它可以与我可能需要注销的任何JSON结构一起使用。
任何帮助都将不胜感激。
答案 0 :(得分:5)
以下是我认为我会采取的方法:
创建一个可以获取字符串值的辅助方法,并以您日志所需的方式隐藏它。也许是这样的,例如:
SCOPES = [ 'openid', 'profile', 'offline_access', 'https://outlook.office.com/mail.read' ]
制作另一个可以接受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
最后,编译一个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表达式区分大小写。)获取此列表并将其放入某个配置设置中,以便在需要时可以轻松更改。
现在,只要你想注销一些JSON,就这样做:
$..credit_card.number
答案 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)))