3

环境:ASP.NET MVC 4、Visual Studio 2012

[Authorize]属性验证用户是否具有有效的登录 cookie,但不验证用户是否实际存在。如果用户被删除,而该用户的计算机仍持有持久的凭据 cookie,则会发生这种情况。在这种情况下,允许登录的非用户运行标有 [Authorize] 属性的控制器操作。

解决方案似乎很简单:扩展AuthorizeAttribute并在 AuthorizeCore 例程中验证用户是否存在。

[Authorize]在我编写此代码供我自己使用之前,我想知道是否有人知道针对属性中这个巨大漏洞的现成解决方案。

4

2 回答 2

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

于 2013-03-09T18:55:51.393 回答
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';
于 2017-08-29T19:49:49.880 回答