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

时间:2014-07-13 22:55:34

标签: c# asp.net-mvc asp.net-mvc-4

如果我的网站收到网址的GET请求,其中包含"有潜在危险"字符,例如:

http://example.com/unsafe:)

然后用户得到一个看起来像服务器有错误的响应(具体来说,服务器在&#34上被阻塞;从客户端检测到一个潜在危险的Request.Path值" HttpException) 。而且,更糟糕的是,用户没有得到我的自定义错误页面(Views / Shared / Error.cshtml),因为全局HandleErrorAttribute没有看到这个特殊的"错误"。因此,用户获得了通用"有些东西被打破但我不会告诉你它是什么,nya nya nya!"页。

我想更改此回复,以便用户获得的内容看起来像我的网站的404页面("无法找到您要求的页面") ,但使用HTTP 400响应代码。

尽可能接近,尝试处理此特定异常的唯一地方是Global.asax Application_Error例程。 (我的自定义全局HandleErrorAttribute没有看到异常。)

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

仅供参考,这是我现有的Global.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接线并且很开心,所以当坏人用我的网站ping我的时候,我每周都会收到几次电子邮件

/w00tw00t.at.blackhats.romanian.anti-sec:)

当我决定压制elmah电子邮件时,整个练习就出现了,我发现更多的良性请求恰好包含了“危险的”#34;字符会导致用户看到一个看起来像我的网站的网页坏了。

轻松删除elmah电子邮件。我想问我是否通过检测Application_Error例程中的错误以正确的方式进行此操作,如果是这样,那么在该例程中做什么是合理的。

2 个答案:

答案 0 :(得分:0)

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

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

很久以前,汉塞尔曼谈到了ELMAH:http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx

你会有这样的事情:

  1. 使用nugget安装ELMAH
  2. 添加到您的网络项目中的过滤器
  3. 只需添加到您的网络配置重定向以查找错误。实施例

    <customErrors mode="On" defaultRedirect="~/Home/Error">
    <error statusCode="404" redirect="~/Home/ErrorBadUrl" />
    </customErrors>
    
  4. 如果您需要整理,可以对global.asax中的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)。

答案 1 :(得分:0)

好的,现在我想我明白从客户端收到的臭名昭着的“危险值”会导致HTTP 400,我可以处理与处理HTTP 404结果完全相同的方式:显示“找不到页面”视图,但保留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处理程序。但这又是另一个问题的主题。