在 ASP .Net Core 2.2 中添加 JWT 令牌后授权不起作用
Authorization does not work after adding JWT token in ASP .Net Core 2.2
我正在学习如何在 ASP 中使用 JWT 令牌身份验证。我有一个带有 CRUD 操作和存储库的简单网站,我添加了 register/login 功能,我有一个名为 "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,
};
});
}
这是我的配置 class:
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 是身份验证,它根本不应该影响授权,所以我想我忘了使用一些额外的选项,但我似乎找不到什么。感谢您的帮助!
我最终完全在 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()));
然后,判断用户是否为管理员就如同从令牌中获取适当的值一样简单:
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;
}
虽然这似乎行得通,但我仍然认为可能有更好的(不那么hacky)的方法来做到这一点,可以更好地将 JWT 集成到身份中,所以如果有人可以提出更简洁的解决方案,我很乐意接受它作为答案而不是我的解决方案。
我正在学习如何在 ASP 中使用 JWT 令牌身份验证。我有一个带有 CRUD 操作和存储库的简单网站,我添加了 register/login 功能,我有一个名为 "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,
};
});
}
这是我的配置 class:
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 是身份验证,它根本不应该影响授权,所以我想我忘了使用一些额外的选项,但我似乎找不到什么。感谢您的帮助!
我最终完全在 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()));
然后,判断用户是否为管理员就如同从令牌中获取适当的值一样简单:
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;
}
虽然这似乎行得通,但我仍然认为可能有更好的(不那么hacky)的方法来做到这一点,可以更好地将 JWT 集成到身份中,所以如果有人可以提出更简洁的解决方案,我很乐意接受它作为答案而不是我的解决方案。