2013-07-12 44 views
2

我正在使用ApiController類來處理ASP.NET MVC4中的Web API。該API將根據簽名驗證進行身份驗證檢查。每個請求都必須使用POST正文和一些密鑰進行簽名。WebApi:驗證json簽名

我也想使用從JSON到對象的模型綁定。

現在我有一個問題。我可以發送JSON和.net很好地將它綁定到對象,但我無法驗證工作。

當POST的Contenttype是application/json時,如何獲取POST內容(以確切形式發送)?

POST內容(應用/ JSON):

{message: "blah"} 

模型類:

public class RequestModel 
{ 
    public String Message { get; set; } 
} 

如何獲得JSON在ApiController?

+0

你在哪裏寫驗證邏輯? –

+0

使用ActionFilterAttribute –

回答

1

您可以使用request.Content.ReadAsStringAsync();作爲字符串讀取請求正文。但是,這不適用於操作方法或過濾器。

在ASP.NET Web API管道中,模型綁定發生在操作過濾器運行之前,然後執行操作方法。模型聯編程序將讀取請求主體(這是一個只讀流)並清空內容。相反,如果您從模型綁定之前運行的組件讀取內容(如消息處理程序),則可以讀取請求主體(在您的情況下爲JSON)。

public class MyHandler : DelegatingHandler 
{ 
    protected override async Task<HttpResponseMessage> SendAsync(
           HttpRequestMessage request, 
            CancellationToken cancellationToken) 
    { 
     var messageBody = await request.Content.ReadAsStringAsync(); 

     return await base.SendAsync(request, cancellationToken); 
    } 
} 

在這裏,messageBody將具有JSON。最好在這裏實現檢查,因爲處理程序在管道中較早運行,並且您希望儘早執行身份驗證。

+0

而且工作正常!謝謝:) –

+1

我發現如果你使用流(ReadyAsStreamAsync),模型綁定將會失敗,因爲它會繼續從你離開的地方讀取流。一旦你提取了messageBody,你必須將流的位置設置回零。 –

0

只要注意,你的json消息應該完全等於你的模型。 (Message屬性沒有消息)

後:

{Message: "blah"} 

模型類:

public class RequestModel 
{ 
    public String Message { get; set; } 
} 

控制器:

[System.Web.Http.HttpPost] 
public RequestModel PostUser(RequestModel model) 
{ 
    //code 
} 
+0

是的,這部分按預期工作,但我需要以精確格式發佈的JSON的字符串形式,如發送(使用空格等)。需要創建請求的散列並與客戶端創建的散列進行比較 –

+0

對不起。你可以使用NewtonSoft(Json庫)嗎? http://james.newtonking.com/pages/json-net.aspx –

+0

不,我需要客戶發送的確切形式的JSON –

0

從請求讀取準確的身體還不夠? :)

Request.InputStream // <-- 
0

在類似靜脈@巴德里的回答上面,當你使用ReadAsStreamAsync(),您必須流的「讀頭」回零,否則模型結合作爲流已經被消耗

public class MyHandler : DelegatingHandler 
{ 
    protected override async Task<HttpResponseMessage> SendAsync(
           HttpRequestMessage request, 
           CancellationToken cancellationToken) 
    { 
     using(var sha = System.Security.Cryptography.SHA256.Create()) 
     { 
      var requestStream = await request.Content.ReadAsStreamAsync(); 
      var shaHash = sha.ComputeHash(requestStream); 
      requestStream.Position = 0; // <-Important!! 
     } 


     return await base.SendAsync(request, cancellationToken); 
    } 
} 
將失敗