Asp Core 2.1 Jwt + 身份。userManager 存储未实现 IUserRoleStore

ova*_*nko 2 c# jwt asp.net-core asp.net-core-identity

我正在尝试在 ASP Net Core 2.1 中使用 Jwt auth 和 Identity

在我的 Startup.cs 中,我有:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = AuthOptions.ISSUER,
            ValidateAudience = true,
            ValidAudience = AuthOptions.AUDIENCE,
            ValidateLifetime = true,
            IssuerSigningKey = AuthOptions.GetSymmetricSecurityKey(),
            ValidateIssuerSigningKey = true,
        };
    });

var builder = services.AddIdentityCore<User>(options =>
{
    // Password settings
    ...
    // Lockout settings
    ...
    // User settings
    options.User.RequireUniqueEmail = true;
}).AddEntityFrameworkStores<ApplicationDbContext>();
Run Code Online (Sandbox Code Playgroud)

builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);

然后在 SecurityService.cs 中我尝试使用此语句来获取角色

var roles = await _userManager.GetRolesAsync(user);
Run Code Online (Sandbox Code Playgroud)

它抛出以下异常:

NotSupportedException:存储未实现 IUserRoleStore
Microsoft.AspNetCore.Identity.UserManager.GetUserRoleStore()

我发现它是因为AddIdentityCore:如果我使用 AddIdentity<User, IdentityRole>它,它可以工作,但然后就[Authorize]不起作用

有没有人遇到过类似的情况,或者为什么会发生?

Kir*_*kin 5

当您使用 时AddIdentity<TUser, TRole>,该调用会配置默认身份验证方案,如下所示(来源):

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
Run Code Online (Sandbox Code Playgroud)

在您的 中Startup.ConfigureServices,您有以下内容,其中设置了默认身份验证方案:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
Run Code Online (Sandbox Code Playgroud)

由于定义的顺序(AddIdentity之后 AddAuthentication),默认值从 Jwt 更改为 Identity,因此当您使用 时[Authorize],身份验证过程现在期望使用 Identity 而不是 Jwt。

AddIdentity要解决此问题,最简单的选择是切换和的顺序AddAuthentication,因此 JwtBearer 调用排在最后,因此“获胜”。您还需要更明确地设置DefaultAuthenticateSchemeDefaultChallengeScheme

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(...);
Run Code Online (Sandbox Code Playgroud)

另一种选择是在属性中明确[Authorize]指出您要使用身份验证方案,例如以下两行之一:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Authorize(AuthenticationSchemes = IdentityConstants.ApplicationScheme)]
Run Code Online (Sandbox Code Playgroud)

似乎第一个选项最适合您的用例,但很高兴知道第二个选项存在,如果您在进一步使用身份时需要它(还有更多 - 例如使用策略)。