【问题标题】:How to correctly configure JWT in asp.net core2?如何在 asp.net core2 中正确配置 JWT?
【发布时间】:2018-06-05 15:04:36
【问题描述】:

我正在尝试在我的api 应用程序中应用基于 JSON Web 令牌的身份验证。问题是每次我测试我的令牌时都会得到无效的令牌签名。此外,我的请求无法在我的控制器中获得授权,我认为这可能与生成后者有关。

我发布所有相关代码,如果有人可以帮助我,我将不胜感激。 源码来源于githubASPNETCore2JwtAuthentication

appsettings.json

 "BearerTokens": {
  "Key": "iNivDmHLpUA223sqsfhqGbMRdRj1PVkH",
  "Issuer": "http://localhost/",
  "Audience": "http://localhost/",
  "AccessTokenExpirationMinutes": 2,
  "RefreshTokenExpirationMinutes": 60
},

Startup.cs / ConfigureServices

            services.AddAuthorization(options =>
                    {
                        options.AddPolicy(CustomRoles.Admin, policy => policy.RequireRole(CustomRoles.Admin));
                        options.AddPolicy(CustomRoles.User, policy => policy.RequireRole(CustomRoles.User));
                        options.AddPolicy(CustomRoles.Editor, policy => policy.RequireRole(CustomRoles.Editor));
                    });


            services.AddAuthentication(options =>
                {
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddCookie(cfg => 
                { 
                    cfg.SlidingExpiration = true; 
                })
                .AddJwtBearer(cfg =>
                {
                    cfg.RequireHttpsMetadata = false;
                    cfg.SaveToken = true;
                    cfg.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidIssuer = Configuration["BearerTokens:Issuer"],
                        ValidAudience = Configuration["BearerTokens:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["BearerTokens:Key"])),
                        ValidateIssuerSigningKey = true,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.Zero
                    };
                    cfg.Events = new JwtBearerEvents
                    {
                        OnAuthenticationFailed = context =>
                        {
                            var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents));
                            logger.LogError("Authentication failed.", context.Exception);
                            return Task.CompletedTask;
                        },
                        OnTokenValidated = context =>
                        {
                            var tokenValidatorService = context.HttpContext.RequestServices.GetRequiredService<ITokenValidatorService>();
                            return tokenValidatorService.ValidateAsync(context);
                        },
                        OnMessageReceived = context =>
                         {
                             return Task.CompletedTask;
                         },
                        OnChallenge = context =>
                        {
                            var logger = context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents));
                            logger.LogError("OnChallenge error", context.Error, context.ErrorDescription);
                            return Task.CompletedTask;
                        }
                    };
                });


            services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy",
                    builder => builder
                        .WithOrigins("http://localhost:4200") //Note:  The URL must be specified without a trailing slash (/).
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });
            services.AddMvc();



**Startup.cs** / Configure


app.UseAuthentication();
app.UseMvc();

TokenStoreService.cs

public async Task<(string accessToken, string refreshToken)> CreateJwtTokens(ApplicationUser user)
{
    var now = DateTimeOffset.UtcNow;
    var accessTokenExpiresDateTime = now.AddMinutes(_configuration.Value.AccessTokenExpirationMinutes);
    var refreshTokenExpiresDateTime = now.AddMinutes(_configuration.Value.RefreshTokenExpirationMinutes);
    var accessToken = await createAccessTokenAsync(user, accessTokenExpiresDateTime.UtcDateTime).ConfigureAwait(false);
    var refreshToken = Guid.NewGuid().ToString().Replace("-", "");

    await AddUserTokenAsync(user, refreshToken, accessToken, refreshTokenExpiresDateTime, accessTokenExpiresDateTime).ConfigureAwait(false); // this method is only to store the generated token in the database, irrelevent to the issue.
    await this.context.SaveChangesAsync();


    return (accessToken, refreshToken);
}

 private async Task<string> createAccessTokenAsync(ApplicationUser user, DateTime expires)
        {
            var claims = new List<Claim>
            {
                // Unique Id for all Jwt tokes
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                // Issuer
                new Claim(JwtRegisteredClaimNames.Iss, _configuration.Value.Issuer),
                // Issued at
                new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToUnixEpochDate().ToString(), ClaimValueTypes.Integer64),
                new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                new Claim(ClaimTypes.Name, user.UserName),
                new Claim("DisplayName", user.LastName),
                // to invalidate the cookie
                new Claim(ClaimTypes.SerialNumber, user.SecurityStamp),
                // custom data
                new Claim(ClaimTypes.UserData, user.Id.ToString())
            };

            // add roles
            var roles = await _rolesService.FindUserRolesAsync(user.Id).ConfigureAwait(false);
            foreach (var role in roles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role.RoleId));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.Value.Key));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: _configuration.Value.Issuer,
                audience: _configuration.Value.Audience,
                claims: claims,
                notBefore: DateTime.UtcNow,
                expires: expires,
                signingCredentials: creds);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

生成的令牌示例

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkODFhNTQ4ZS0xOWFlLTRhNDQtODZhMS0zY2ZiNWU0MmE4ZDkiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0LyIsImlhdCI6MTUxNDAwODYwOCwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZWlkZW50aWZpZXIiOiIwYjk0NWZkZC00ZjViLTRhMmEtODNiZi0yNTA1YjBkNjJiODUiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSlNPTiIsIkRpc3BsYXlOYW1lIjoiQWJ1IE1haXphciIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0eS9jbGFpbXMvc2VyaWFsbnVtYmVyIjoiNTU0Zjg5ZjMtZjRiMi00ODY0LThiMzctZWNmMGY2OGNlOWM0IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy91c2VyZGF0YSI6IjBiOTQ1ZmRkLTRmNWItNGEyYS04M2JmLTI1MDViMGQ2MmI4NSIsIm5iZiI6MTUxNDAwODYwNywiZXhwIjoxNTE0MDA4NzI3LCJhdWQiOiJodHRwOi8vbG9jYWxob3N0LyJ9.q-IphSwiOhzDT9upOO4XOvGQVp_NxymcuW4WWuERe2U P>

validation link

【问题讨论】:

  • 我写了一步一步的博文,希望对你有帮助mostafizz.wordpress.com/2017/09/30/…
  • 同样的问题,你的代码被 cookie 唤醒,但 JWT 没有
  • 我希望您在尝试验证 JWT 时确实提供了密钥。我认为 JWT 没有任何问题。您提供的 JWT 验证链接将始终显示无效签名,直到您提供用于生成 JWT 的密钥

标签: c# authentication jwt asp.net-core-2.0 bearer-token


【解决方案1】:

所以我的问题是我的 ITokenValidatorService 中的一个错误,这是您验证自己的令牌的自定义方式。

 OnTokenValidated = context =>
                        {
                            var tokenValidatorService = context.HttpContext.RequestServices.GetRequiredService<ITokenValidatorService>();
                            return tokenValidatorService.ValidateAsync(context);
                        },

上面显示的配置工作正常

但我仍然想知道为什么 JWT validator 总是将任何提交的令牌返回为无效!

【讨论】:

    猜你喜欢
    • 2021-11-16
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 2020-10-31
    • 2013-05-08
    • 2021-02-02
    • 1970-01-01
    相关资源
    最近更新 更多