仅支持HTTPS的网站对HTTP HEAD请求的正确响应

10
我们有一个ASP.Net MVC3网站,只能通过HTTPS访问,使用控制器上的RequireHTTPS属性。
我们收到了大量HTTP HEAD方法请求,主要来自似乎是Twitter机器人。默认的ASP.Net/MVC3响应是“500内部服务器错误”,并且被elmah和log4net捕获/记录(现在已被过滤掉!)。
我可以编写一个特定的控制器和路由来处理这些非HTTPS请求,就像这个问题中所述 - Responding to HEAD Request in asp.NET MVC 3
但是,从机器人的角度来看,什么是最好的响应?200表示服务器正在运行,302重定向到HTTPS网址,还是保持500,因为该网站无法通过HTTP访问?

500 不太对啊...这里难道没有对应的状态码吗?状态码 500 暗示着确实存在某个错误。 - Andrew Barber
2
我建议不要抛出500错误。如果网站只能通过HTTPS访问,我会使用301重定向(永久)而不是302(临时)。您还可以使用重写规则将所有非HTTPS流量重定向到HTTPS以解决此问题。 - Nick Bork
同意不抛出500错误,但这是MVC3的默认行为:System.InvalidOperationException: The requested resource can only be accessed via SSL. at System.Web.Mvc.RequireHttpsAttribute.HandleNonHttpsRequest(AuthorizationContext filterContext) at System.Web.Mvc.RequireHttpsAttribute.OnAuthorization(AuthorizationContext filterContext) at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor)` - Chris
2个回答

3

您可以回复以下内容:

405 Method Not Allowed

这意味着

请求行中指定的方法不允许用于由请求URI标识的资源。响应必须包含一个Allow头,其中列出了请求资源的有效方法列表。

或者使用

501 Not Implemented

这意味着:

服务器不支持实现请求所需的功能。当服务器不识别请求方法并且无法为任何资源提供支持时,这是适当的响应。

就个人而言,我会选择 405,因为它是客户端错误,更适合使用类似于“嘿,伙计,我们这里不提供这种东西”的表述,而不是使用类似于“你在说什么鬼?我不明白。”的表述,后者是由于 501 描述中的 服务器不识别请求方法 一段建议使用的。

所有HTTP状态码: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html


4
“405 方法不被允许”不是正确的响应。使用HTTP而不是HTTPS并不是使用不允许的方法。http(s)是URI中的“协议”,而方法是发送的请求类型,可以是以下任何一种:GETHEADPOSTPUTDELETECONNECTOPTIONSTRACEPATCH(请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)。抛出405将会告诉客户端发生错误,不正确。 - Fat Monk

1
在我的情况下,我只收到了针对网站根目录/的HEAD请求,这似乎是机器人的探测。因此,我有点担心返回500或404。
更多关于405的信息
按照Albireo的回答,405可能是可以接受的,但您需要返回接受的动词,例如:
// 405 must include allowable methods.
// https://tools.ietf.org/html/rfc2616#section-14.7
httpContext.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
httpContext.Response.AddHeader( "Allow", "GET" );

302选项

查看MVC代码中不重定向HEAD请求的注释:

//only redirect for GET requests, otherwise the browser might not propagate the verb and request
//body correctly.

似乎另一个选项是发送302。对于机器人HEAD请求到根目录(这是MVC为GET所做的操作),返回一个302到HTTPS站点应该是相当安全的。因此,我实现了以下基于MVC方式的代码:
if( isHead == true && isRoot == true )
{
    httpContext.ClearError();
    httpContext.Response.Clear();                    
    httpContext.Response.StatusCode = 302;
    string url = "https://" + httpContext.Request.Url.Host + httpContext.Request.RawUrl;
    httpContext.Response.Redirect(url, endResponse: false);                    
    return;
}

在 global.asax.cs 中实现:
protected void Application_Error( object sender, EventArgs e )
{
     //Your code here
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接