我正在为外部移动公司构建一个WebAPI(我所做的只是暴露服务)。
现在,我们的数据库使用非加密值作为列:
但现在,当我们公开它时,我需要加密值。 (只有服务器可以解密值,移动公司不关心实际值。)
我不想手动启动摘要每个存储过程响应,并用加密值替换值。 (不要忘记我们的内部服务器不使用加密值 - 它会定期使用数据)。
确定以下是一个实例:
我有这个控制器代码:
[HttpGet]
[ActionName("test2")]
public HttpResponseMessage test2(int id)
{
var Data = GetDataFromSource_1();
// or from GetDataFromSource_2();
return Request.CreateResponse(HttpStatusCode.OK, Data);
}
GetDataFromSource_1
通过动态列表(仅用于模拟源)
public IEnumerable GetDataFromSource_1()
{
List<dynamic> lst = new List<dynamic>();
lst.Add(new
{
objId = 1,
myOtherColumn = 5
});
lst.Add(new
{
objId = 2,
myOtherColumn = 8
});
return lst;
}
并且
GetDataFromSource_2
是通过DataTable(只是模拟其他来源)
public DataTable GetDataFromSource_2()
{
DataTable dt = new DataTable("myTable");
dt.Columns.Add("objId", typeof(int));
dt.Columns.Add("myOtherColumn", typeof(int));
DataRow row = dt.NewRow();
row["objId"] = 1;
row["myOtherColumn"] = 5;
dt.Rows.Add(row);
row = dt.NewRow();
row["objId"] = 2;
row["myOtherColumn"] = 8;
dt.Rows.Add(row);
return dt;
}
两者都产生了这个json响应:
{ “结果”:{ “成功”:真, “消息”: “”}, “数据”:[{ “OBJID”:1, “myOtherColumn”:5},{ “OBJID”:2“, myOtherColumn“:8}]}
问题
如何(以及在何处)我可以扫描响应的内容(将要发送的内容)并替换为(和仅)中的每一列:
到加密值?
例如:
我希望输出为:
{
"Result": {
"Success": true,
"Message": ""
},
"Data": [{
"objId": "XXX_the_encrypted_valueXXX",
"myOtherColumn": 5
}, {
"objId": "XXX_the_encrypted_valueXXX": ,
"myOtherColumn": 8
}]
}
(其中"XXX_the_encrypted_valueXXX"
是旧值的加密值。)
请注意,我有Utils.Encrypt(string st)
方法。
另外,我们没有实体,所以我无法装饰实体。我需要在创建json时插件
答案 0 :(得分:1)
我认为你应该使用Attribute
:
[JsonEncryptValue]
public Guid ObjectID {get;set;}
然后添加一个JsonConverter
,它只会处理属性为JsonEncryptValue
的属性。
您可以轻松地重写它们的价值。
然后您需要做的就是将JsonConverter
添加到JsonSerializer
文件中的WebApiConfig.cs
:
JsonMediaTypeFormatter jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
JsonSerializerSettings jSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
Formatting = Formatting.Indented,
DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
jSettings.Converters.Add(new EncryptionJsonConverter());
jsonFormatter.SerializerSettings = jSettings;
答案 1 :(得分:1)
您可以通过派生自定义DelegatingHandler
并提供自己的实施并将其注册为config.MessageHandlers
来创建自定义private static void FindTokens(JToken containerToken, string name, List<JToken> matches)
{
if (containerToken.Type == JTokenType.Object)
{
foreach (JProperty child in containerToken.Children<JProperty>())
{
if (child.Name == name)
{
matches.Add(child.Value);
}
FindTokens(child.Value, name, matches);
}
}
else if (containerToken.Type == JTokenType.Array)
{
foreach (JToken child in containerToken.Children())
{
FindTokens(child, name, matches);
}
}
}
。
所以我们需要一个处理程序和一个迭代整个JSON的递归方法。我们将使用Searching for a specific JToken by name in a JObject hierarchy中提供的答案:
public class JsonEncrypterHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
var returnedJson = await response.Content.ReadAsStringAsync();
JObject jObj = JObject.Parse(returnedJson);
List<JToken> objIdTokens = new List<JToken>();
List<JToken> policyIdTokens = new List<JToken>();
FindTokens(jObj, "objid", objIdTokens);
FindTokens(jObj, "policyid", policyIdTokens);
foreach (JValue objId in objIdTokens)
{
objId.Value = Utils.Encrypt(objIdValue);
}
foreach (JValue policyId in policyIdTokens)
{
policyId.Value = Utils.Encrypt(policyIdTokens);
}
response.Content = JsonConvert.SerializeObject(jObj);
return response;
}
}
完整的处理程序如下所示:
{{1}}
答案 2 :(得分:0)
我认为你必须创建客户属性。用该属性装饰所有动作或控制器。
在那里你必须读取结果并反序列化回Json对象或.net对象。
以下链接可以帮助您。