将HttpException转换为HTTP 404(未找到页面)响应

本文关键字:响应 转换 HttpException HTTP | 更新日期: 2023-09-27 18:12:56

如果我的站点收到一个带有"潜在危险"字符的URL GET请求,例如:

http://example.com/unsafe:)

则用户得到一个响应,看起来像是服务器有一个错误(具体来说,服务器阻塞了"一个潜在危险的请求")。从客户端"HttpException"检测到路径值。而且,更糟糕的是,用户没有得到我的自定义错误页面(Views/Shared/error .cshtml),因为全局HandleErrorAttribute没有看到这个特定的"错误"。所以用户得到的是一般的"有东西坏了,但我不会告诉你是什么,nya nya nya!"页面。

我想改变这个响应,这样用户得到的东西看起来像我的网站的404页面("找不到你要找的页面"),但有一个HTTP 400响应代码。

据我所知,尝试处理这个特殊异常的唯一地方是在全局。asax Application_Error例程。(我的自定义全局HandleErrorAttribute看不到异常)

任何帮助或指导(或一个尖锐的巴掌在手腕上试图做一些我不应该试图做的事情)将不胜感激!

供参考,这是我现有的全球。asax代码:

    /// <summary> Handle "page not found" (HTTP 404) errors. </summary>
    protected void Application_EndRequest()
    {
        // This code is from: http://stackoverflow.com/a/9026941/1637105
        if (Context.Response.StatusCode == 404) {
            Response.Clear();
            var rd = new RouteData();
            rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
            rd.Values["controller"] = "Errors";
            rd.Values["action"] = "NotFound";
            IController c = new ErrorsController();
            c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        }
    }
    protected void Application_Error(object sender, EventArgs e)
    {
        // Convert "A potentially dangerous Request.Path value was detected from the client" to an HTTP 404 (page not found) response
        var ex = Server.GetLastError();
        if (ex != null && ex is HttpException) {
            var re = new Regex(@"(?ix: 'b potentially 'b.+?'b dangerous 'b.+?'b value 'b.+?'b detected 'b.+?'b client 'b )");
            if (re.IsMatch(ex.Message)) {
                // <Convert the response to 404>
            }
        }
    }
编辑:

我应该补充说,我的elmah很开心,所以当坏人用

访问我的网站时,我每周会收到几次电子邮件。
/w00tw00t.at.blackhats.romanian.anti-sec:)

当我决定抑制elmah电子邮件时,我发现更良性的请求碰巧包含"危险"字符,导致用户得到一个非常丑陋的网页,看起来像我的网站坏了。

抑制elmah邮件很容易。我想我是在问,通过检测Application_Error例程中的错误,我是否以正确的方式处理这个问题,如果是这样,在该例程中做什么是合理适当的事情。

将HttpException转换为HTTP 404(未找到页面)响应

我总是尝试记录异常,它们中的大多数并不重要,但仍然很高兴看到它们。创建或更好地使用现有的错误处理库(http://msdn.microsoft.com/en-us/library/aa479332.aspx)。

在你的情况下,我会使用ELMAH来处理它们,写入日志文件/数据库,并向用户显示自定义错误页面,给他一些错误id,并选择联系支持。

Hanselman很久以前谈到ELMAH: http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx

你可以这样写:

  1. 使用nuget安装ELMAH
  2. 添加到web项目中的过滤器
  3. 只需添加到您的web配置重定向错误。示例

    <customErrors mode="On" defaultRedirect="~/Home/Error">
    <error statusCode="404" redirect="~/Home/ErrorBadUrl" />
    </customErrors>
    

你可以对全局的ErrorLog_Logged事件进行操作。如果你需要整理东西,就去找。

附加:我曾经创建Elmah过滤器,但不确定这是必要的,以防万一这是示例代码:

public class ElmahErrorFilter : IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        // Long only handled exceptions, because all other will be caught by ELMAH anyway.
        if (filterContext.ExceptionHandled)
            ErrorSignal.FromCurrentContext().Raise(filterContext.Exception);
    }
}

编辑:如果对记录错误不感兴趣,可以使用IIS客户错误页面(http://www.iis.net/configreference/system.webserver/httperrors)。

好的,所以现在我想我明白了臭名昭著的"从客户端收到的危险值"导致HTTP 400,我可以完全相同的方式处理我处理HTTP 404结果:显示"page not found"视图,但保留HTTP状态代码。

对我现有的错误处理代码做了一个小小的调整,似乎正是我想要它做的:

    /// <summary> Handle "page not found" (HTTP 404) and "dangerous/invalid syntax" (HTTP 400) errors. </summary>
    protected void Application_EndRequest()
    {
        // This code is adapted from: https://stackoverflow.com/a/9026941/1637105
        var code = Context.Response.StatusCode;
        if (code == 404 || code == 400) {
            Response.Clear();
            var rd = new RouteData();
            rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
            rd.Values["controller"] = "Errors";
            rd.Values["action"] = "NotFound";
            IController c = new ErrorsController();
            c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        }
    }

和相关的控制器代码(也改编自https://stackoverflow.com/a/9026941/1637105):

)
public class ErrorsController : Controller
{
    /// <summary> GET: /Errors/NotFound </summary>
    public ActionResult NotFound()
    {
        object model = Request.Url.PathAndQuery;
        if (!Request.IsAjaxRequest()) {
            return View(model);
        } else {
            return PartialView("_NotFound", model);
        }
    }
}

,当然,您需要Views/Errors/NotFound.cshtml中的关联视图。

注意,在这个问题的上下文中,我删除了Application_Error例程,它对这个答案没有任何贡献。

但显然,如果我想要健壮的错误重定向(包括发生在MVC管道之外的错误),我需要使用Application_Error处理程序。但这是另一个问题的主题。