WebAPI可以在响应之前更改输出吗?

时间:2014-11-24 10:27:16

标签: c# asp.net-web-api

我正在为外部移动公司构建一个WebAPI(我所做的只是暴露服务)。

现在,我们的数据库使用非加密值作为列:

  • ObjectID
  • 策略ID
  • 等。

但现在,当我们公开它时,我需要加密值。 (只有服务器可以解密值,移动公司不关心实际值。)

我不想手动启动摘要每个存储过程响应,并用加密值替换值。 (不要忘记我们的内部服务器使用加密值 - 它会定期使用数据)。

确定以下是一个实例:

我有这个控制器代码:

[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}]}

问题

如何(以及在​​何处)我可以扫描响应的内容(将要发送的内容)并替换为(和)中的每一列:

  • ObjectID
  • 策略ID
  • 等。

加密值?

例如:

我希望输出为:

{
    "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时插件

3 个答案:

答案 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对象。

以下链接可以帮助您。

http://damienbod.wordpress.com/2014/01/04/web-api-2-using-actionfilterattribute-overrideactionfiltersattribute-and-ioc-injection/

相关问题