3

我正在使用带有asp.net核心webapi模板的角度v6我想将Xsrf令牌与身份授权一起发送到角度应用程序我的问题在用户登录时开始。如果HttpContext.User中没有用户,则令牌没有问题,但是当用户登录并重新生成令牌时,我的所有发布请求都失败,状态码为 400(因为 Xsrf-token 无效),这是我的服务配置:

            services.Configure<ApiSettings>(options => Configuration.GetSection("ApiSettings").Bind(options));

        services.AddAuthentication(options =>
        {
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        })
          .AddJwtBearer(options =>
        {
            options.Audience = "Any";
            options.RequireHttpsMetadata = false;
            options.SaveToken = true;

            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = "http://localhost:44330/",
                ValidAudience = "http://localhost:44330/",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VeryStrongKey#123"))
            };

        });

        services.AddIdentity<User, Role>();

        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "/Ui";
        });

        services.AddAntiforgery(x => { x.HeaderName = "X-XSRF-TOKEN";x.Cookie.Name = "XSRF-TOKEN"; });
        services.AddMvc(options =>
        {
            options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);




        var builder = new ContainerBuilder();

        services.AddScoped<IAntiForgeryCookieService, AntiForgeryCookieService>();
        services.AddScoped<ITokenStoreService, TokenStoreService>();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        builder.Populate(services);
        builder.RegisterModule(new ManagementService.Service.DiRegister());
        return new AutofacServiceProvider(builder.Build());

和我的应用程序配置:

  app.UseStaticFiles();
        app.UseSpaStaticFiles();
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseAuthentication();
        app.UseMvc();
        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "Ui";
            if (env.IsDevelopment())
            {
                spa.UseAngularCliServer(npmScript: "start");
            }
        });

这是我在成功登录事件后生成用户声明的方式:

 public async Task<(string AccessToken, List<Claim> claims)> createAccessTokenAsync(User user,List<string> roles)
    {


        var claims = new List<Claim>
        {
            // Unique Id for all Jwt tokes
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString(), ClaimValueTypes.String, "http://localhost:44330/"),
            // Issuer
            new Claim(JwtRegisteredClaimNames.Iss, "http://localhost:44330/", ClaimValueTypes.String, "http://localhost:44330/"),
            // Issued at
            new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64, "http://localhost:44330/"),
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString(), ClaimValueTypes.String, "http://localhost:44330/"),
            new Claim(ClaimTypes.Name, user.UserName, ClaimValueTypes.String, "http://localhost:44330/"),
            new Claim("DisplayName", user.Firstname + " " + user.LastName, ClaimValueTypes.String, "http://localhost:44330/"),
         //   new Claim(ClaimTypes.SerialNumber, user.SerialNumber, ClaimValueTypes.String, "http://localhost:44330/"),
            new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String, "http://localhost:44330/")
        };

        // add roles
        //var roles = await _rolesService.FindUserRolesAsync(user.Id);
        foreach (var role in roles)
        {
            claims.Add(new Claim(ClaimTypes.Role, role, ClaimValueTypes.String, "http://localhost:44330/"));
        }

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VeryStrongKey#123"));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var now = DateTime.UtcNow;
        var token = new JwtSecurityToken(
            issuer: "http://localhost:44330/",
            audience: "http://localhost:44330/",
            claims: claims,
            notBefore: now,
            expires: now.AddMinutes(20),
            signingCredentials: creds);
        return (new JwtSecurityTokenHandler().WriteToken(token), claims);
    }

以及创建声明后的令牌再生:

  public string RegenerateAntiForgeryCookies(ClaimsPrincipal claims)
    {
        var httpContext = _contextAccessor.HttpContext;
        httpContext.User = claims;
       // httpContext.SignInAsync(claims);

        var tokens = _antiforgery.GetAndStoreTokens(httpContext);
        DeleteAntiForgeryCookies();
        httpContext.Response.Cookies.Append(
             key: XsrfTokenKey,
              value: tokens.RequestToken,
              options: new CookieOptions
              {
                  HttpOnly = false // Now JavaScript is able to read the cookie
              });
        return tokens.RequestToken;
    }

我确定客户端应用程序将发送令牌: 在此处输入图像描述

我使用了 antiforgery.ValidateRequestAsync(HttpContext); 为了得到确切的错误:

在此处输入图像描述

4

0 回答 0