将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例程中的错误,我是否以正确的方式处理这个问题,如果是这样,在该例程中做什么是合理适当的事情。
我总是尝试记录异常,它们中的大多数并不重要,但仍然很高兴看到它们。创建或更好地使用现有的错误处理库(http://msdn.microsoft.com/en-us/library/aa479332.aspx)。
在你的情况下,我会使用ELMAH来处理它们,写入日志文件/数据库,并向用户显示自定义错误页面,给他一些错误id,并选择联系支持。
Hanselman很久以前谈到ELMAH: http://www.hanselman.com/blog/ELMAHErrorLoggingModulesAndHandlersForASPNETAndMVCToo.aspx
你可以这样写:
- 使用nuget安装ELMAH
- 添加到web项目中的过滤器
-
只需添加到您的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处理程序。但这是另一个问题的主题。