【问题标题】:AntiforgeryToken validation failedAntiforgeryToken 验证失败
【发布时间】:2018-12-28 18:38:00
【问题描述】:

我有 ASP CORE 2.1 应用程序,它与 Angular SPA 客户端一起工作。 我按照here 的说明保护了我的应用程序。

但问题是我在登录系统后经常收到 400 Bad Request。根据我的观点,这就是系统中发生的事情:

  1. 对应用程序的第一个请求 -> 返回 AntiForgery CookieToken 和 RequestToken(重要提示,用户尚未通过身份验证
  2. 用户登录系统 -> AntiForgery 验证通过, 发送到客户端的身份验证 cookie。
  3. 用户请求任何 其他端点,但由于 AntiforgeryTokenSet 是为 未经身份验证的用户,他会收到 400 Bad Request。

很明显,登录后我们需要重新发布 AntiforgeryTokenSet 但我不知道在哪里以及如何。我尝试在结果过滤器中发出令牌,但没有成功。

public class SPAAntiforgeryCookieResultFilter : ResultFilterAttribute
    {
        private readonly IAntiforgery _antiforgery;

        public SPAAntiforgeryCookieResultFilter(IAntiforgery antiforgery)
        {
            _antiforgery = antiforgery;
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            Action assignAntiForgery = () =>
            {
                var tokens = _antiforgery.GetAndStoreTokens(context.HttpContext);
                context.HttpContext.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
            };

            if (context.Result is ViewResult)
            {
                assignAntiForgery();
            }
            else if (string.Equals(context.ActionDescriptor.ActionName, nameof(AccountController.Login), StringComparison.OrdinalIgnoreCase))
            {
                assignAntiForgery();
            }
        }
    }

似乎 ResultExecutingContext 不知道经过身份验证的用户,并且仍然为匿名用户颁发令牌。 那么,我们如何在认证用户登录后立即刷新防伪 RequestToken 令牌?

【问题讨论】:

    标签: authentication antiforgerytoken asp.net-core-2.1


    【解决方案1】:

    现在我找到了解决问题的方法。

    以前,我在成功登录后返回Ok(),但现在我返回RedirectToAction(),并且我的OnResultExecuting 过滤器稍作更改,以便在RedirectToAction 发生后刷新令牌。

        public class SPAAntiforgeryCookieResultFilter : ResultFilterAttribute
            {
                private readonly IAntiforgery _antiforgery;
    
                public SPAAntiforgeryCookieResultFilter(IAntiforgery antiforgery)
                {
                    _antiforgery = antiforgery;
                }
    
                public override void OnResultExecuting(ResultExecutingContext context)
                {
                    Action assignAntiForgery = () =>
                    {
                        var tokens = _antiforgery.GetAndStoreTokens(context.HttpContext);
                        context.HttpContext.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
                    };
    
                    if (context.Result is ViewResult)
                    {
                        assignAntiForgery();
                    }
                    // Here we check whether our redirect action is executed. Update AFT if it is
                    else if (string.Equals(context.ActionDescriptor.RouteValues["action"], nameof(AccountController.RefreshAntiForgeryAfterLogin), StringComparison.OrdinalIgnoreCase))
                    {
                        assignAntiForgery();
                    }
                }
            }
    

    这种肮脏的技巧以下列方式起作用:

    1. 对应用程序的第一个请求 -> 返回 AntiForgery CookieToken 和 RequestToken(重要说明,用户尚未通过身份验证)
    2. 用户按下登录系统 -> AntiForgery 验证通过,身份验证 cookie 设置 -> 用户通过身份验证 cookie 和状态码 302(重定向)获得响应 -> 用户通过 上下文联系我们的 RedirectUserToAction 方法有身份验证信息 (User.IsAuthenticated == true)

    【讨论】:

      猜你喜欢
      • 2018-06-10
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 2011-10-07
      • 2016-08-24
      • 2012-03-15
      • 2011-01-02
      • 2012-10-18
      相关资源
      最近更新 更多