2014-11-24 77 views
1

我正在爲外部移動公司構建一個WebAPI(我所做的只是公開服務)。WebAPI可以在響應之前更改輸出嗎?

眼下,我們的DB使用非加密值列,如:

  • 對象ID
  • 策略ID
  • 等。

但是現在,當我們揭露它,我需要加密值。 (只有服務器可以解密值,移動公司不關心實際值)。

我不想開始摘要手動存儲過程響應並用加密值替換值。 (不要忘記,我們的內部服務器不是而是使用加密值 - 它定期使用數據)。

OK這裏是一個活生生的例子:

我有這樣的控制器代碼:

[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是經由數據表(只是爲了模擬另一個源)

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

問題

如何(和wher E)我可以掃描響應(這是將被髮送的內容),並替換爲在每一個柱(和他們的):

  • 的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"是舊值的加密值。)

NB它可假設我有Utils.Encrypt(string st)方法。

此外,我們沒有實體,所以我不能裝飾實體。我需要插件時創建JSON

+0

是加密變量所有metohd電話一樣嗎?或者它們有所不同? – 2014-11-24 10:41:20

+0

@yuval,無論如何,如果響應結果中包含一個名爲:(查找)的列,請將其值轉換爲加密的值 – 2014-11-24 10:43:19

+0

這些列名在所有查詢中是否相同或是否有所不同?你怎麼知道哪個列名需要加密? – 2014-11-24 10:44:12

回答

1

你可以做的是通過推導,並提供自己的實現創建一個自定義DelegatingHandler並註冊你的config.MessageHandlers

所以我們需要一個處理程序和迭代整個JSON的遞歸方法。我們將使用在Searching for a specific JToken by name in a JObject hierarchy提供了答案:

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); 
     } 
    } 
} 

以及完整的處理程序將看起來如下:

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; 
    } 
} 
+0

它會做它recursivly? – 2014-11-24 11:41:20

+0

'數據'可以包含任何東西。正如我的問題所述:_如何掃描響應內容(將要發送的內容)並替換每個列的內容(並且僅針對他們)** _ – 2014-11-24 11:43:28

+0

這就是爲什麼我詢問屬性是否爲常量。意思是,你只想改變'objId'和'policyId'。我會再問一次。你知道你想要加密的屬性嗎? – 2014-11-24 11:45:17

1

我想你應該裝飾用Attribute加密屬性:

[JsonEncryptValue] 
public Guid ObjectID {get;set;} 

,然後添加一個JsonConverter將處理只對他們有JsonEncryptValue屬性的屬性。 您可以輕鬆地重寫它們的值。

然後所有你需要做的就是在WebApiConfig.cs文件添加JsonConverterJsonSerializer

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; 
+0

我沒有屬性。在我們的項目中沒有實體,所以我沒有什麼可以裝飾的 – 2014-11-24 10:46:55

+0

哦...你總是可以創建醜陋的解決方法,比如創建一個替換的httpmodule。我想有一個更好的做法,雖然。 – 2014-11-24 10:53:39

相關問題