.NET Core返回值處理(手機身份證號碼脫敏)的三種方式
阿新 • • 發佈:2021-11-22
在已有業務下面新增脫敏需求,不允許汙染源方法,所以只能自定義序列化或者過濾器處理返回值,自定義序列化應對所有用到該實體類的情況,過濾器應對只需要某一個或幾個Action脫敏的情況;
在已有業務下面新增脫敏需求,不允許汙染源方法,所以只能自定義序列化或者過濾器處理返回值,自定義序列化應對所有用到該實體類的情況,過濾器應對只需要某一個或幾個Action脫敏的情況;
如果僅僅處理脫敏,直接使用通用脫敏工具類即可。
通用脫敏工具類程式碼如下
點選檢視程式碼
public static class DesensitizationUtil { /// <summary> /// 將傳入的字串中間部分字元替換成特殊字元 /// </summary> /// <param name="value">需要替換的字串</param> /// <param name="startLen">前保留長度,預設4</param> /// <param name="subLen">要替換的長度,預設4</param> /// <param name="specialChar">特殊字元,預設為*</param> /// <returns>替換後的結果</returns> public static string ReplaceWithSpecialChar(this string value, int startLen = 4, int subLen = 4, char specialChar = '*') { if (value.Length <= startLen + subLen) return value; string startStr = value.Substring(0, startLen); string endStr = value.Substring(startLen + subLen); string specialStr = new string(specialChar, subLen); return startStr + specialStr + endStr; } }
方式一:JsonConverter
引用:
using Newtonsoft.Json;
點選檢視程式碼
public class DesensitizationConvter : JsonConverter { //關閉反序列化 public override bool CanRead => false; //開啟自定義序列化 public override bool CanWrite => true; public override bool CanConvert(Type objectType) { return true; } private readonly int StartLen; private readonly int SubLen; private readonly char SpecialChar; /// <summary> /// 預設前保留長度4,脫敏長度4,特殊字元為* /// </summary> public DesensitizationConvter() { StartLen = 4; SubLen = 4; SpecialChar = '*'; } /// <summary> /// 根據傳入的長度進行脫敏 /// </summary> /// <param name="startLen">前保留長度</param> /// <param name="subLen">脫敏長度</param> public DesensitizationConvter(int startLen, int subLen) : this() { StartLen = startLen; SubLen = subLen; } /// <summary> /// 根據傳入的長度及特殊字元進行脫敏 /// </summary> /// <param name="startLen">前保留長度</param> /// <param name="subLen">脫敏長度</param> /// <param name="specialChar">替換的特殊字元</param> public DesensitizationConvter(int startLen, int subLen, char specialChar) : this(startLen, subLen) { SpecialChar = specialChar; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value != null) { writer.WriteValue(value.ToString().ReplaceWithSpecialChar(StartLen, SubLen, SpecialChar)); } } }
然後在實體類需要脫敏的屬性上面加上修飾
[JsonConverter(typeof(DesensitizationConvter))]
public string Phone { get; set; }
[JsonConverter(typeof(DesensitizationConvter), 3, 4)]
public string Phone2 { get; set; }
[JsonConverter(typeof(DesensitizationConvter), 4, 10, '*')]
public string IDCard { get; set; }
方式二:過濾器(JObject遍歷)
引用:
using Newtonsoft.Json.Linq;
using System.Linq;
點選檢視程式碼
public class DesensitizationAttribute : Attribute, IActionFilter
{
public string[][] Desensitizations { get; set; }
public DesensitizationAttribute(params string[] desensitizations)
{
Desensitizations = new string[desensitizations.Length][];
for (int i = 0; i < desensitizations.Length; i++)
{
desensitizations[i] = desensitizations[i].Replace(",", ",");
string[] str = desensitizations[i].Split(',');
switch (str.Count())
{
case 1:
Desensitizations[i] = new string[4] { str[0].Trim(), "4", "4", "*" };
break;
case 3:
Desensitizations[i] = new string[4] { str[0].Trim(), str[1].Trim(), str[2].Trim(), "*" };
break;
case 4:
Desensitizations[i] = new string[4] { str[0].Trim(), str[1].Trim(), str[2].Trim(), str[3].Trim() };
break;
default:
break;
}
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result != null && context.Result is ObjectResult)
{
ObjectResult obj = context.Result as ObjectResult;
//轉換成JObject
JObject jo = JObject.FromObject(obj.Value);
//如果已知需要替換的欄位層級關係,直接查詢脫敏即可,例如傳入A.B.Phone
//foreach (var item in Desensitizations)
//{
// if (jo.SelectToken(item[0]) != null)
// {
// string newStr = jo.SelectToken(item[0]).ToString().ReplaceWithSpecialChar(Convert.ToInt32(item[1]), Convert.ToInt32(item[2]), Convert.ToChar(item[3]));
// jo.SelectToken(item[0]).Replace(newStr);
// }
//}
// 如果不知道層級,使用下面方法遍歷JObject
foreach (JToken item in jo.Values()){
CommonReplaceConvter(item);
}
context.Result = new ObjectResult(jo);
}
}
/// <summary>
/// 遞迴遍歷JToken脫敏
/// </summary>
/// <param name="jt"></param>
public void CommonReplaceConvter(JToken jt)
{
if (jt == null) return;
if (jt.HasValues && jt.Values().Count() > 0)
{
foreach (JToken item in jt.Values())
{
CommonReplaceConvter(item);
}
}
else
{
string[] str = Desensitizations.FirstOrDefault(t => t[0] == jt.Path.Split('.').Last());
if (str != null)
{
string result = jt == null ? "" : jt.ToString().ReplaceWithSpecialChar(Convert.ToInt32(str[1]), Convert.ToInt32(str[2]), Convert.ToChar(str[3]));
jt.Replace(result);
}
}
}
}
在Controller上新增修飾:
[Desensitization("Phone", "Phone2,3,4", "IDCard,4,10,*")]
方式三:過濾器(反射)
引用:
using System.Collections;
using System.Linq;
using System.Reflection;
點選檢視程式碼
public class DesensitizationAttribute : Attribute, IActionFilter
{
public string[][] Desensitizations { get; set; }
public DesensitizationAttribute(params string[] desensitizations)
{
Desensitizations = new string[desensitizations.Length][];
for (int i = 0; i < desensitizations.Length; i++)
{
desensitizations[i] = desensitizations[i].Replace(",", ",");
string[] str = desensitizations[i].Split(',');
switch (str.Count())
{
case 1:
Desensitizations[i] = new string[4] { str[0].Trim(), "4", "4", "*" };
break;
case 3:
Desensitizations[i] = new string[4] { str[0].Trim(), str[1].Trim(), str[2].Trim(), "*" };
break;
case 4:
Desensitizations[i] = new string[4] { str[0].Trim(), str[1].Trim(), str[2].Trim(), str[3].Trim() };
break;
default:
break;
}
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Result != null && context.Result is ObjectResult)
{
ObjectResult obj = context.Result as ObjectResult;
GetInfoPropertys(obj.Value);
context.Result = obj;
}
}
/// <summary>
/// 反射的方式遞迴脫敏
/// </summary>
/// <param name="obj">需要脫敏的物件</param>
public void GetInfoPropertys(object obj)
{
if (obj == null) return;
Type type = obj.GetType();
if (type.IsGenericType)
{
//如果是List,需要遍歷
if (obj is ICollection Ilist)
{
foreach (object o in Ilist)
{
GetInfoPropertys(o);
}
}
return;
}
foreach (PropertyInfo property in type.GetProperties())
{
object value = property.GetValue(obj, null);
if (property.PropertyType.IsValueType || property.PropertyType.Name.StartsWith("String"))
{
string[] str = Desensitizations.FirstOrDefault(t => t[0] == property.Name);
if (str != null)
{
string result = value == null ? "" : value.ToString().ReplaceWithSpecialChar(Convert.ToInt32(str[1]), Convert.ToInt32(str[2]), Convert.ToChar(str[3]));
property.SetValue(obj, result, null);
}
}
else
{
GetInfoPropertys(value);
}
}
}
}
在Controller上新增修飾:
[Desensitization("Phone", "Phone2,3,4", "IDCard,4,10,*")]