我在WebAPI中实现了一个自定义AuthorizeAttribute(请注意,这与MVC AuthorizeAttribute不同)。
我已经重写了OnAuthorization方法。在这个方法中,我检查用户是否通过了身份验证。如果未通过身份验证,我会要求用户登录。
我的自定义逻辑的一部分是检查经过身份验证的用户是否有权继续(基本上我会检查他们的姓名/电子邮件。如果它存在于预定义的列表中,那么他们有权访问)。
我看到的问题是:在用户成功验证但未能获得授权后,我看到有一个无限循环重定向到登录页面。
同样,用户凭据的挑战在于OnAuthorization方法。是什么原因导致了这种无限循环,一旦用户被确定没有授权,如何防止这种情况发生?
*更新了代码片段*
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnAuthorization(actionContext); // Should this be here?
var owinContext = HttpContext.Current.GetOwinContext();
var authenticated = owinContext.Authentication.User.Identity.IsAuthenticated;
var request = System.Web.HttpContext.Current.Request;
if (!authenticated)
{
// Challenge user for crednetials
if (!request.IsAuthenticated)
{
// This is where the user is requested to login.
owinContext.Authentication.Challenge(
new AuthenticationProperties { RedirectUri = "/" },
WsFederationAuthenticationDefaults.AuthenticationType);
}
}
else
{
// At this point the user ia authenticated.
// Now lets check if user is authorized for this application.
var isAuthorized = SecurityHelper.IsUserAuthorized();
if (isAuthorized)
{
// authorized.
return;
}
// not authorized.
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
}
您可以尝试删除OnAuthorization并添加以下内容:
protected override bool IsAuthorized(HttpActionContext actionContext)
{
var owinContext = HttpContext.Current.GetOwinContext();
var authenticated = owinContext.Authentication.User.Identity.IsAuthenticated;
return authenticated & SecurityHelper.IsUserAuthorized();
}
我不明白你为什么重定向失败的身份验证,API肯定应该只返回401?
我想知道这里的这段代码:
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
在某个地方,您必须使用以下内容配置OWIN层:
var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
LoginPath = new PathString(loginPath)
}
app.UseCookieAuthentication(cookieAuthenticationOptions);
当您从身份验证过滤器返回401时,OWIN基础结构将自动将您重定向到您指定的任何登录路径。但是,当试图满足该请求时,它会调用您的过滤器,但由于用户未被授权,它会返回401,从而导致重定向到LoginPath,依此类推
因为这是一个API调用,所以您需要以不同的方式处理401。下面的博客文章谈到了这种情况。
http://brockallen.com/2013/10/27/using-cookie-authentication-middleware-with-web-api-and-401-response-codes/
简而言之,在配置CookieAuthenticationOptions
时,您需要指定自己的Provider
,并且仅当它不是AJAX请求时才直接指定。
var cookieAuthenticationOptions = new CookieAuthenticationOptions
{
LoginPath = new PathString(loginPath),
Provider = new CookieAuthenticationProvider()
{
OnApplyRedirect = context =>
{
if (!context.Request.IsAjaxRequest())
{ context.Response.Redirect(context.RedirectUri); }
}
}
}