在ASP .Net Core 2.2中添加JWT令牌后,授权不起作用

时间:2019-11-01 11:23:35

标签: asp.net-core asp.net-core-webapi asp.net-authorization jwt-auth

我正在学习如何在ASP中使用JWT令牌身份验证。我有一个带有CRUD操作和存储库的简单网站,添加了注册/登录功能,并且只有一个名为“ Administrator”的角色,它是超级用户。通常,这是我检查用户当前是否以管理员身份登录的方式:

bool admin = User.IsInRole(Constants.ADMIN_ROLE);

直到我将JWT身份验证添加到我的应用程序之前,该功能才能正常工作。现在,使用我的管理员帐户(手动添加到数据库)登录,我再也无法获得正确的值。当我尝试查询用户时,我得到NULL:

var user = await _userManager.GetUserAsync(HttpContext.User)

这是我在Startup.cs中的ConfigureServices:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

        services.AddIdentity<MyUser, MyRole>()
            .AddEntityFrameworkStores<MyContext>()
            .AddRoles<MyRole>();


        services.AddDbContext<MyContext>(builder =>
        {
            builder.UseSqlServer(Configuration["ConnectionStrings"]);
        });

        // repo code here ommitted for clarity

        var appSettingsSection = Configuration.GetSection("AppSettings");
        services.Configure<AppSettings>(appSettingsSection);

        var appSettings = appSettingsSection.Get<AppSettings>();
        var key = Encoding.ASCII.GetBytes(appSettings.Secret);
        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false,
                ValidateLifetime = true,
            };

        });

    }

这是我的Configure类:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseAuthentication();
        app.UseMvc();
        app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    }

我非常了解,由于JWT是身份验证,因此它根本不会影响授权,因此我想我忘记使用一些其他选项,但是我似乎找不到任何东西。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

我最终完全在JWT中实现了身份验证。

在创建令牌描述符的过程中,我在令牌内添加了新的用户声明:

                  ... 
 Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.Name, userId.ToString()),
                new Claim(ClaimTypes.Role, roleId)
            }),
                  ...

并添加与内部角色有关的信息(在我的例子中,我使用角色的ID来减少描述性,以防有人破解)

var roles = await _userManager.GetRolesAsync(userInDb);
var userRoleId = await _roleManager.FindByNameAsync(roles.First());
                       ...
return Ok(_tokenService.GenerateToken(userInDb.Id, userRoleId.Id.ToString()));

然后,确定用户是否为admin就像从令牌中获取适当的值一样简单:

private async Task<bool> IsUserAdmin()
{
    var roleId = Guid.Parse(User.Claims.FirstOrDefault(e => e.Type == "role").Value);
    var adminId = (await _roleManager.FindByNameAsync(Constants.ADMIN_ROLE))?.Id;     
    return roleId == adminId;
}

尽管这似乎可行,但我仍然认为可能会有更好的方法(减少黑客攻击),以更好地将JWT集成到身份中,因此,如果有人可以提出更简洁的解决方案,我很乐意接受回答而不是我的解决方案。