我有一个带有Web Api 2的标准VS2013 MVC5项目。标准项目的设计方式,如果请求未经过身份验证,[Authorize]
属性只返回401状态代码,而完全独立的模块会嗅探任何401代码,暂停它们,然后将302重定向发送到Startup.Auth.cs
文件中指定的登录页面。这对于Mvc控制器来说没问题,但是对于Web Api控制器来说真的很糟糕,因为例如浏览器会自动将ajax请求重定向到登录URL,所以即使响应文本只是登录页面的html,你最终也会得到200OK状态。
这使得编写好的javascript变得难以区分,这种javascript可以区分您只需要告诉用户重新登录的情况与其他类型的错误。理想情况下,我们应该能够根据状态代码判断,但javascript永远不会看到401状态。处理这个问题的最佳方法是什么?
我的第一个想法是编写授权属性,但使用状态代码403而不是401:
public class ApiAuthorizationAttribute : System.Web.Http.AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.RequestContext.Principal.Identity.IsAuthenticated)
{
base.OnAuthorization(actionContext);
}
else
{
actionContext.Response = actionContext.ControllerContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Not signed in.");
}
}
}
当然,specifications明确声明403不正确:
授权无效,请求不应重复
我的另一个想法是,我可能会完全禁用asp.net的401重定向模块并处理自定义授权属性中的重定向,因为即使对于Mvc视图也很糟糕,因为它不允许您重定向到不同的登录页面,具体取决于在用户试图访问的网站中的哪个位置。
还有其他更好的方法来处理这个吗?
答案 0 :(得分:0)
这是我能通过更多研究找到的东西。 401被OWIN中间件拦截。但是,OWIN确实使用Map
方法支持分支配置。所以在Startup.cs
文件中我有这个:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.Map(new PathString("/api"), site => ConfigureAuth2(site));
ConfigureAuth(app);
}
}
其中ConfigureAuth
是Startup.Auth.cs
文件中的默认配置方法,而ConfigureAuth2
是该方法的副本,但未指定LoginPath
选项UseCookieAuthentication
方法,如下所示:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
根据documentation,当LoginPath
未指定时,401响应将不会被截获。
因此,通过这种方法,我将所有请求分支为两种不同的配置 - 所有/api
请求都配置为不重定向401状态,而其他所有请求都配置为重定向到登录页面。 / p>
此SO question谈了一些关于分支配置的内容。
我仍然不确定这是否是最佳方法。