1. 程式人生 > 其它 >.NET Core返回值處理(手機身份證號碼脫敏)的三種方式

.NET Core返回值處理(手機身份證號碼脫敏)的三種方式

在已有業務下面新增脫敏需求,不允許汙染源方法,所以只能自定義序列化或者過濾器處理返回值,自定義序列化應對所有用到該實體類的情況,過濾器應對只需要某一個或幾個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,*")]