【问题标题】:WebApi: verification of json signingWebApi:验证 json 签名
【发布时间】:2023-03-25 01:14:01
【问题描述】:

我正在使用 ApiController 类在 ASP.NET MVC4 中开发 Web API。 API 将基于签名验证进行身份验证检查。每个请求都必须使用 POST 正文和一些密钥进行签名。

我还想使用从 JSON 到对象的模型绑定。

现在我有一个问题。我可以发送 JSON,.net 将它很好地绑定到对象,但我无法进行验证。

当 POST 的 Contenttype 为 application/json 时,我如何获取 POST 内容(以发送的确切形式)?

例子

POST 内容(应用程序/json):

{message: "blah"}

模型类:

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

如何在 ApiController 中获取 JSON?

【问题讨论】:

  • 你在哪里写验证逻辑?
  • 使用 ActionFilterAttribute

标签: asp.net asp.net-mvc asp.net-mvc-4 asp.net-web-api


【解决方案1】:

您可以使用request.Content.ReadAsStringAsync(); 将请求正文读取为字符串。但是,这在 action 方法或过滤器中不起作用。

在 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。最好在此处实施检查,因为处理程序在管道中运行得更早,您将希望尽早强制执行身份验证。

【讨论】:

  • 我发现如果您使用流 (ReadyAsStreamAsync),模型绑定将失败,因为它会继续从您离开的位置读取流。提取 messageBody 后,必须将流位置设置回零。
【解决方案2】:

请注意,您的 json 消息应该与您的模型完全相同。 (消息属性不是消息)

发帖:

{Message: "blah"}

模型类:

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

控制器:

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

【讨论】:

  • 是的,这部分按预期工作,但我需要 JSON 的字符串形式,以与发送时完全相同的形式发布(带有空格等)。需要创建请求的哈希并与客户端创建的进行比较
  • 对不起。你可以使用 NewtonSoft(Json 库)吗? james.newtonking.com/pages/json-net.aspx
  • 不,我需要客户端发送的 JSON 格式
【解决方案3】:

从 Request 中读取确切的正文还不够吗? :)

Request.InputStream // <--

【讨论】:

    【解决方案4】:

    与上面@Badri 的回答类似,当您使用 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 2016-08-28
      • 2019-07-25
      • 2011-08-01
      • 2011-08-18
      • 2018-12-19
      相关资源
      最近更新 更多