最初开发时,System.Web.Mvc.AuthorizeAttribute 做的是正确的事 - HTTP 规范的旧版本使用状态代码 401 表示“未授权”和“未验证”。
从原始规范:
如果请求已包含授权凭证,则 401 响应表示已拒绝对这些凭证的授权。
实际上,您可以在此处看到混乱-它在表示“身份验证”时使用了“授权”一词。然而,在日常实践中,当用户通过身份验证但未授权时,返回 403 Forbidden 更有意义。用户不太可能拥有第二组可以授予他们访问权限的凭据 - 到处都是糟糕的用户体验。
考虑大多数操作系统 - 当您尝试读取您无权访问的文件时,您不会看到登录屏幕!
值得庆幸的是,HTTP 规范已更新(2014 年 6 月)以消除歧义。
来自“超文本传输协议(HTTP/1.1):身份验证”(RFC 7235):
401(未授权)状态码表示该请求尚未应用,因为它缺少目标资源的有效身份验证凭据。
来自“超文本传输协议 (HTTP/1.1):语义和内容”(RFC 7231):
403(Forbidden)状态码表示服务器理解请求但拒绝授权。
有趣的是,在 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);
}
}
}