【问题标题】:.NET Core 3.1, Vue, Axios and [ValidateAntiForgeryToken].NET Core 3.1、Vue、Axios 和 [ValidateAntiForgeryToken]
【发布时间】:2020-08-18 05:50:44
【问题描述】:

我整天都在玩这个,尽可能多地阅读,但我完全没能做到这一点。

我已将我的实现与 MS 文档和其他围绕 SO 的答案进行了比较,但似乎没有一种方法有效。

问题的根源在于匿名用户和登录用户的切换。

我一直遵循 MS 的建议 here。以及各种答案herehere

为了进行测试,我有一个联系表格,其端点用[ValidateAntiForgeryToken] 装饰。

流程是:

访问网站,发布此表单,一切正常。 登录 访问表单,发布 - BOOM - 提供的防伪令牌适用于与当前用户不同的基于声明的用户。

在我的public void Configure( 方法中,我有:

app.Use(async (context, next) =>
{
        var tokens = antiforgery.GetAndStoreTokens(context);
        context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });

    await next();
});

在我的public void ConfigureServices( 方法中,我有:

services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");

在我的 Vue 路由器中,我添加了对我的 axios API 上的方法的调用,如下所示:

router.afterEach((to, from) => {
    api.readCsrfCookieAndSetHeader();
});

这个方法只是读取cookie并更新header:

public readCsrfCookieAndSetHeader() {
    console.info('READING CSRF-TOKEN');
    if (document.cookie.indexOf('CSRF-TOKEN') > -1) {
        const v = document.cookie.match('(^|;) ?' + 'CSRF-TOKEN' + '=([^;]*)(;|$)');
        const r = v ? v[2] : '';
        // console.log(r);
        this.csrfToken = r;
        axios.defaults.headers.common['X-CSRF-TOKEN'] = this.csrfToken;
        console.log(axios.defaults.headers.common['X-CSRF-TOKEN']);
    } else {
        this.csrfToken = '';
    }
}

我可以看到这个值逐页变化。一个似乎对某些人有用的建议是在用户登录时重新运行GetAndStoreTokens,例如:

var user = await _userManager.FindByEmailAsync(userName);
var result = await _signInManager.PasswordSignInAsync(user, password, true, false);
_httpContextAccessor.HttpContext.User = await _signInManager.CreateUserPrincipalAsync(user);
if (result.Succeeded)
{
    // get, store and send the anti forgery token
    AntiforgeryTokenSet tokens = _antiforgery.GetAndStoreTokens(_httpContextAccessor.HttpContext);
    _httpContextAccessor.HttpContext.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false });
}

return result;

但这对我也不起作用。

我也尝试使用 axios 拦截器更新值,如下所示:

axios.interceptors.response.use(
    (response) => {
        // this.readCsrfCookieAndSetHeader();
        return response;
    }, 
    (error) => {

但这实际上只是另一种获取更新值的方法,我确信它已经被更新了。

我的想法已经用完了,而且似乎还有一些可以尝试的东西。所以这个Q。

我错过了什么明显的东西吗?似乎我几乎逐字复制了 MS Angular 示例,所以我不知道自己做错了什么。

任何指针将不胜感激。

【问题讨论】:

  • 哦主啊,你刚刚给我这个帖子可怕的闪回。我的 Core & Angular 应用程序遇到了完全相同的问题。我有这样的假记忆,这与app.Use 语句的顺序有关。我将在答案中发布我的 Startup.cs,它可能会有所帮助...
  • 你,先生。很可能即将获得一颗金星...... :)

标签: c# vue.js asp.net-core axios antiforgerytoken


【解决方案1】:

正如 cmets 关于您的问题所讨论的那样。我有一个虚假的记忆,它与 AppStartup 中的某些东西的排序有关。这是我所拥有的转储。这目前有效(似乎很好)。

    /// <summary>
    /// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    /// </summary>
    /// <param name="app">The <see cref="IApplicationBuilder"/>.</param>
    /// <param name="env">The <see cref="IHostingEnvironment"/>.</param>
    /// <param name="antiforgery">Enables setting of the antiforgery token to be served to the user.</param>
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAntiforgery antiforgery)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
            {
                HotModuleReplacement = true,
            });
        }

        app.UseSession();

        app.UseHttpsRedirection();

        app.UseStaticFiles();

        // global cors policy
        app.UseCors(x => x
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader());

        // Authenticate before the user accesses secure resources.
        app.UseAuthentication();

        app.Use(next => context =>
        {
            string path = context.Request.Path.Value;
            if (path.IndexOf("a", StringComparison.OrdinalIgnoreCase) != -1 || path.IndexOf("b", StringComparison.OrdinalIgnoreCase) != -1)
            {
                // The request token can be sent as a JavaScript-readable cookie,
                // and Angular uses it by default.
                var tokens = antiforgery.GetAndStoreTokens(context);
                context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
            }

            return next(context);
        });

        app.Use(next => context =>
        {
            string timezone = context.Request.Headers["Timezone"];

            if (!string.IsNullOrEmpty(timezone))
            {
                context.Session.SetString(nameof(HttpContextSessionValues.SessionStrings.Timezone), timezone);
            }

            return next(context);
        });

        app.UseExceptionHandler(errorApp =>
        {
            errorApp.Run(async context =>
            {
                context.Response.StatusCode = 500;
                context.Response.ContentType = "text/html";

                var exHandlerFeature = context.Features.Get<IExceptionHandlerFeature>();
                var exception = exHandlerFeature.Error;

                if (exception is PresentableException)
                {
                    await context.Response.WriteAsync(exception.Message).ConfigureAwait(false);
                }
                else
                {
                    await context.Response.WriteAsync("An Unexpected error has occured. You may need to try again.").ConfigureAwait(false);
                }
            });
        });
        app.UseHsts();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
    }

【讨论】:

  • 刚刚比较,将app.use 移动到app.UseAuthentication()app.UseAuthorisation() 之后,一切都开始工作了!!!!谢谢!现在看起来很明显。
  • @Jammer 我很高兴能提供帮助。这花了我很长时间才第一次解决.....
  • 确实,非常感谢。我什至在当天早些时候尝试移动东西,但显然没有移动正确的东西!!!
【解决方案2】:

HttpContextSessionValues.SessionStrings.Timezone 的定义在哪里?

【讨论】:

  • 这不是答案,您应该将其添加为评论。
  • @Jammer...我试过了,但是在我获得 50 名声望之前,stackowerflow 不允许我评论不是我的帖子...
猜你喜欢
  • 2020-06-10
  • 2020-04-10
  • 2022-06-30
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
  • 2020-06-18
  • 1970-01-01
相关资源
最近更新 更多