带有SecureString的JSON ToObject

时间:2017-05-31 14:28:52

标签: c# .net json serialization json.net

我无法将JSON文本序列化为包含SecureString变量的对象。我如何在保持公共'pwd'变量为SecureString的同时序列化以下内容?

假设有以下字符串:

string j_str = "{ 'uid':'JohnDoe', 'age':30, 'pwd':'MyPassword' }";

我希望将此字符串序列化为C#

中的对象
public class User
{
   public string uid = { get; set; }
   public string age = { get; set; }
   public SecureString pwd = { get; set; }
}

所以我可以使用JSON ToObject调用以下调用Newtonsoft,如下所示:

JObject j_obj = JObject.Parse(j_str);

User newUser = j_obj.ToObject<User>();

这会导致以下错误:

Newtonsoft.Json.JsonSerializationException: 'Error converting value "MyPassword" to type 'System.Security.SecureString'. Path 'pwd'

2 个答案:

答案 0 :(得分:6)

从字符串构造它似乎违背了使用SecureString背后的原则。见guard.service.ts

  

永远不应该从String构造SecureString对象,   因为敏感数据已经受到内存的影响   不可变String类的持久性结果。最好的方法   构造SecureString对象来自一次一个字符   非托管源,例如Console.ReadKey方法。

答案 1 :(得分:0)

如前所述,这确实违反了 SecureString 的原则。但这里有一个 SecureString 的 JSON 转换器,您可以使用。

using System.Runtime.InteropServices;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public class SecureStringConverter : JsonConverter<SecureString>
{
    public override void WriteJson(JsonWriter writer, SecureString value, JsonSerializer serializer)
    {
        IntPtr ptr = Marshal.SecureStringToBSTR(value);
        writer.WriteValue(Marshal.PtrToStringBSTR(ptr));
        Marshal.ZeroFreeBSTR(ptr);
    }

    public override SecureString ReadJson(JsonReader reader, Type objectType, SecureString existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        string json_val = (string)reader.Value;
        SecureString s = new SecureString();

        if (json_val != null) 
        {
            foreach (char c in json_val) 
            {
                s.AppendChar(c);
            }
        }
        s.MakeReadOnly();
        return s;
    }
}

要序列化用户:

string serialized_user = JsonConvert.SerializeObject(user, new SecureStringConverter());

去序列化serialized_user:

User deserialized_user = JsonConvert.DeserializeObject<User>(serialized_user, new SecureStringConverter());