【问题标题】:ASP.NET Web API removing HttpError from responsesASP.NET Web API 从响应中删除 HttpError
【发布时间】:2013-07-09 11:54:59
【问题描述】:

我正在使用 Microsoft ASP.NET Web API 构建 RESTful 服务。

我的问题涉及 Web API 在出现问题时(例如 400 Bad Request 或 404 Not Found)返回给用户的 HttpErrors。

问题是,我不想在响应内容中获得序列化的 HttpError,因为它有时会提供太多信息,因此它违反了 OWASP 安全规则,例如:

请求:

http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555

作为回应,我当然得到 400,但包含以下内容信息:

{
 "$id": "1",
 "Message": "The request is invalid.",
 "MessageDetail": "The parameters dictionary contains a null entry for parameter 'id'  of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}

这样的东西不仅表明我的 WebService 是基于 ASP.NET WebAPI 技术(这还不错),而且它还提供了一些关于我的命名空间、方法名称、参数等的信息。

我尝试在 Global.asax 中设置 IncludeErrorDetailPolicy

GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;

是的,效果不错,现在结果不包含 MessageDetail 部分,但我仍然不想得到这个 HttpError。

我还构建了我的自定义 DelegatingHandler,但它也会影响我自己在控制器中生成的 400 和 404,这是我不希望发生的。

我的问题是: 有什么方便的方法可以从响应内容中删除序列化的 HttpError 吗?我希望用户得到他的错误请求的只是响应代码。

【问题讨论】:

    标签: asp.net asp.net-web-api response http-error


    【解决方案1】:

    我相信您使用消息处理程序的方法是正确的,因为无论 Web API 管道中将状态代码设置为 4xx 的组件如何,消息处理程序都可以清除响应正文。但是,您确实希望区分您明确设置的内容与其他组件设置的内容。这是我的建议,我承认这有点hacky。如果您没有其他更好的解决方案,请尝试一下。

    在您的 ApiController 类中,当您抛出 HttpResponseException 时,请在请求属性中设置一个标志,如下所示。

    Request.Properties["myexception"] = true;
    throw new HttpResponseException(...);
    

    在消息处理程序中,检查属性,如果设置了属性,则不清除响应正文。

    var response = await base.SendAsync(request, cancellationToken);
    
    if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException"))
        response.Content = null;
    
    return response;
    

    您可以通过向 HttpRequestMessage 添加一个扩展方法来很好地封装它,这样ApiController 和消息处理程序都不知道我在上面使用的硬编码字符串“myException”。

    【讨论】:

    • 这当然行得通,但正如您所说,与其说是长期解决方案,不如说是解决问题。
    【解决方案2】:

    使用自定义 IHttpActionInvoker 怎么样? 基本上,您只需发送一个空的 HttpResponseMessage。

    这是一个非常基本的例子:

    public class MyApiControllerActionInvoker : ApiControllerActionInvoker
    {
        public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
            var result = base.InvokeActionAsync(actionContext, cancellationToken);
    
            if (result.Exception != null)
            {
                //Log critical error
                Debug.WriteLine("unhandled Exception ");
    
                return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError));
            }
            else if (result.Result.StatusCode!= HttpStatusCode.OK)
            {
                //Log critical error
                Debug.WriteLine("invalid response status");
    
                return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode));
            }
    
    
            return result;
        }
    }
    

    在 Global.asax 中

    GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker());
    

    您可以做的另一件与 Web Api 无关的重要事情是删除过多的 asp.net 和 IIS HTTP 标头。 Here 是一个很好的解释。

    【讨论】:

    • 好吧,我想这会很好,但在我的应用程序中,我返回我自己的 HttpResponseMessages,有时是 400 Bad Request,例如,如果有人想向我的数据库插入新记录,他使用控制器 PostNewRecord 方法。他插入的记录通过验证,如果它检测到缺少某些字段,控制器将返回 Bad Request 并带有我自己的消息,即某些字段为空。在您的解决方案中,MyApiControllerActionInvoker 将拦截该响应,并删除我不希望发生的消息。我只想删除 Web API 生成的消息。
    猜你喜欢
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 2013-07-14
    • 1970-01-01
    相关资源
    最近更新 更多