Ral*_*h N 12 model-view-controller
我在提琴手上注意到[RequireHttps]状态代码302重定向而不是301.我不确定这有多大意义......
如果你说的是控制器[RequireHttps],那么你永远不会希望人们去访问那个页面的Http版本.那么为什么不是永久重定向...告诉搜索引擎"请将您的链接永久更新到此页面的https版本".
如果这是有道理的,我是对的,有没有办法将其更改为301重定向?
Dulan的答案很接近,但它不起作用,至少我们的MVC 4+解决方案.但经过一些试验和错误,我们确实得到了我们的301而不是302的工作.这是新课程:
public class CustomRequireHttpsAttribute : RequireHttpsAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
#if !DEBUG
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.Request.IsSecureConnection)
{
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
filterContext.Result = new RedirectResult(url, true);
}
#endif
}
}
Run Code Online (Sandbox Code Playgroud)
PermanentDulan 的答案不起作用的原因似乎是因为filterContext.Result 的属性是只读的,并且只能在RedirectResult()调用时设置,并且问题是RedirectResult()在base.OnAuthorization()方法中调用的.所以只需调用base方法,然后filterContext.Result使用第二个参数true 覆盖下面的方法,使结果为Permanent.在这之后,我们开始在Fiddler2中看到301个代码.
好像选择302超过301的选择开始时有点武断.但是,并不一定表明每个URL都"必须"使用HTTPS方案.很可能是允许HTTP或HTTPS访问的页面,即使它可能鼓励后者.可能发生这种情况的实现可能会将某些代码连接起来以确定是否根据某些特殊条件使用HTTPS.
作为案例,请查看Gmail.在这些设置中,可以在应用程序的大部分内容中允许或禁止HTTPS协议.那么应该返回哪些代码?301不准确,因为它不是"永久的"......只是在用户的要求下的变化.遗憾的是,302不太准确,因为302错误意味着有意在未来的某个时刻改变链接(相关参考文献http://www.w3.org/Protocols/rfc2616/rfc2616-sec10. HTML).
当然,Gmail是一个粗略的例子,因为允许该选项的网站部分通常不被搜索引擎索引,但可能性仍然存在.
回答你的最后一个问题,如果你想在ASP.NET MVC中使用不同的状态代码(我假设你使用的是小语法示例),可以使用简单的自定义属性进行更改:
public class MyRequireHttpsAttribute : RequireHttpsAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!filterContext.HttpContext.Request.IsSecureConnection)
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,实现该属性的所有操作都应在通过HTTP协议访问时返回301状态代码.
Dulan 的解决方案让我走上了正确的道路,但代码示例并没有阻止核心 RequireHttpsAttribute 实现的 302 重定向。因此,我查找了 RequireHttpsAttribute 的代码并对其进行了破解。这是我想出的:
using System.Net;
using System.Web.Mvc;
using System;
using System.Diagnostics.CodeAnalysis;
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "Unsealed because type contains virtual extensibility points.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class RequireHttps301Attribute : FilterAttribute, IAuthorizationFilter
{
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null) {
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.Request.IsSecureConnection) {
HandleNonHttpsRequest(filterContext);
}
}
protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
// only redirect for GET requests, otherwise the browser might not propagate the verb and request
// body correctly.
if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException("Only redirect for GET requests, otherwise the browser might not propagate the verb and request body correctly.");
}
// redirect to HTTPS version of page
string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
//what mvc did to redirect as a 302
//filterContext.Result = new RedirectResult(url);
//what I did to redirect as a 301
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.MovedPermanently;
filterContext.HttpContext.Response.RedirectLocation = url;
}
}
Run Code Online (Sandbox Code Playgroud)