环境:ASP.NET MVC 4,Visual Studio 2012
[Authorize]
属性验证用户是否具有有效的登录cookie,但它不验证用户是否确实存在。如果在该用户的计算机仍保留持久凭证cookie时删除用户,则会发生这种情况。在这种情况下,允许登录的非用户运行标有[Authorize]属性的控制器操作。
解决方案看起来非常简单:扩展AuthorizeAttribute
,并在AuthorizeCore例程中验证用户是否存在。
在我编写此代码供我自己使用之前,我想知道是否有人知道[Authorize]
属性中这个漏洞的现成解决方案。
答案 0 :(得分:3)
您的问题的解决方案如下。您必须引入将在调用控制器操作之前执行的全局操作筛选器。此事件名为OnActionExecuting
。在此全局操作过滤器中,您还可以处理用户具有有效身份验证cookie但在持久性(DB)中不再存在的方案(并且您必须删除其cookie)。
以下是获得想法的代码示例:
public class LoadCustomPrincipalAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CustomIdentity customIdentity;
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
UserData userData = UserRepository.GetUserByName(HttpContext.Current.User.Identity.Name);
if (userData == null)
{
//TODO: Add here user missing logic,
//throw an exception, override with the custom identity with "false" -
//this boolean means that it have IsAuthenticated on false, but you
//have to override this in CustomIdentity!
//Of course - at this point you also remove the user cookie from response!
}
customIdentity = new CustomIdentity(userData, true);
}
else
{
customIdentity = new CustomIdentity(new UserData {Username = "Anonymous"}, false);
}
HttpContext.Current.User = new CustomPrincipal(customIdentity);
base.OnActionExecuting(filterContext);
}
}
希望对你有所帮助!
不要忘记将此操作过滤器注册为全局过滤器。你可以这样做:
private static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LoadCustomPrincipalAttribute());
}
只是添加这个。别管AuthorizeAttribute
。它应该按照它的意思工作。它只是检查HttpContext.Current.User.Identity.IsAuthenticated == true
条件。有些情况下你需要覆盖它,但这不是那个。在AuthorizeAttribute
开始之前,您确实需要正确的用户/身份验证处理。
答案 1 :(得分:0)
同意彼得。这是我为AngularJs应用程序所做的。创建一个检查锁定日期的属性。使用正确的方法更改YourAppUserManager。
public class LockoutPolicyAttribute : ActionFilterAttribute
{
public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
var now = DateTime.UtcNow;
var currentUserId = Convert.ToInt32(HttpContext.Current.User?.Identity?.GetUserId());
var user = await HttpContext.Current.GetOwinContext().GetUserManager<YourAppUserManager>().FindByIdAsync(currentUserId);
if (user?.LockedOutUntil >= now)
{
actionContext.Response = actionContext.Request.CreateErrorResponse((HttpStatusCode)423, "Account Lockout");
return;
}
}
base.OnActionExecuting(actionContext);
}
}
然后让状态代码423的AngularJs拦截服务重定向到登录页面。
switch (response.status) {
case 423: //Account lockout sent by the server.
AuthService.logOut();
window.location.href = '/login';