最初开发时,System.Web.Mvc.AuthorizeAttribute做正确的事-HTTP规范的旧版本对“未经授权”和“未经身份验证”使用状态码401。
从原始规格:
如果请求已包含授权凭证,则401响应指示已拒绝这些凭证的授权。
实际上,您可以在此处看到混乱-它在表示“身份验证”时使用“授权”一词。但是,在日常实践中,当用户经过身份验证但未经授权时,返回403 Forbidden是更有意义的。用户不太可能拥有第二组凭据来授予他们访问权限-糟糕的用户体验。
考虑大多数操作系统-尝试读取您无权访问的文件时,不会显示登录屏幕!
值得庆幸的是,HTTP规范已更新(2014年6月)以消除歧义。
来自“超文本传输协议(HTTP / 1.1):身份验证”(RFC 7235):
401(未经授权)状态码表示该请求尚未应用,因为它缺少针对目标资源的有效身份验证凭据。
来自“超文本传输协议(HTTP / 1.1):语义和内容”(RFC 7231):
403(禁止)状态码表示服务器理解了请求,但拒绝授权。
有趣的是,在发布ASP.NET MVC 1时,AuthorizeAttribute的行为是正确的。现在,该行为是不正确的-HTTP / 1.1规范已修复。
与其尝试更改ASP.NET的登录页面重定向,还不如尝试从源头上解决问题,这更容易。您可以在网站的默认名称空间中创建一个具有相同名称(AuthorizeAttribute
)的新属性(这很重要),然后编译器将自动选择它,而不是MVC的标准属性。当然,如果您愿意采用这种方法,则可以始终为属性指定一个新名称。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : System.Web.Mvc.AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
{
filterContext.Result = new System.Web.Mvc.HttpStatusCodeResult((int)System.Net.HttpStatusCode.Forbidden);
}
else
{
base.HandleUnauthorizedRequest(filterContext);
}
}
}