ASP.Net Core 3.0 JWT Bearer Token 没有 SecurityTokenValidator 可用
Posted
技术标签:
【中文标题】ASP.Net Core 3.0 JWT Bearer Token 没有 SecurityTokenValidator 可用【英文标题】:ASP.Net Core 3.0 JWT Bearer Token No SecurityTokenValidator available 【发布时间】:2019-10-18 20:26:59 【问题描述】:我使用 ASP.Net Core 3.0 API 和 EntityFramework Core 作为 UserStorage。 启动.cs:
public void ConfigureServices(IServiceCollection services)
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
.
.
.
//Add Identity Provider with EntityFramework
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDBContext>()
.AddDefaultTokenProviders();
//Initialize EntityFramework
services.AddDbContext<ApplicationDBContext>(options => options.UseSqlite(Configuration.GetConnectionString("localDB")));
//Initialize JWT Authentication
services.AddAuthentication(options =>
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
).AddJwtBearer(jwtBearerOptions =>
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:44352",
ValidAudience = "http://localhost:44352",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("Secrets")["jwt"]))
;
);
services.AddMvc(options => options.EnableEndpointRouting = false)
.AddNewtonsoftJson();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
configuration.RootPath = "ClientApp/dist";
);
.
.
.
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
//Enable Authentication
app.UseAuthentication();
app.UseAuthorization();
.
.
.
app.UseMvc(routes =>
routes.MapRoute(
name: "default",
template: "controller/action=Index/id?");
);
.
.
.
这是我发出 JWT 令牌的代码:
public async Task<IActionResult> Login()
using (var reader = new StreamReader(Request.Body))
var body = await reader.ReadToEndAsync();
var cred = JsonConvert.DeserializeObject<Credentials>(body);
var result = (await userService.LoginUser(cred.userName, cred.password));
if (result == 200)
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration.GetSection("Secrets")["jwt"]));
var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256Signature);
var roles = await userService.GetRoleFromUsername(cred.userName);
var rolesString = JsonConvert.SerializeObject(roles);
var tokeOptions = new JwtSecurityToken(
issuer: "http://localhost:44352",
audience: "http://localhost:44352",
claims: new List<Claim>(new List<Claim>
new Claim("userName",cred.userName),
new Claim("roles", rolesString)
),
expires: DateTime.Now.AddHours(1),
signingCredentials: signinCredentials
);
这是我使用授权的 API 调用:
[Route("api/videos/add")]
[Authorize(Roles = "Admin")]
[HttpPost]
public async Task<IActionResult> AddVideo()
using (var reader = new StreamReader(Request.Body))
var body = await reader.ReadToEndAsync();
var video = JsonConvert.DeserializeObject<Video>(body);
await videoService.AddVideo(video);
return Ok();
我的 NuGet 包是:
Microsoft.EntityFrameworkCore 3.0.0-preview5.19227.1 Microsoft.EntityFrameworkCore.Sqlite 3.0.0-preview5.19227.1 Microsoft.AspNetCore.Authentication.JwtBearer 3.0.0-preview4-19216-03 Microsoft.EntityFrameworkCore.Sqlite.Core 3.0.0-preview5.19227.1 Microsoft.NETCore.Platforms 3.0.0-preview4.19212.13 Microsoft.AspNetCore.Mvc.NewtonsoftJson 3.0.0-preview5-19227-01 Microsoft.AspNetCore.SpaServices.Extensions 3.0.0-preview5-19227-01 Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.0.0-preview5-19227-01 runtime.win-x64.Microsoft.NETCore.DotNetAppHost 3.0.0-preview4-27615-11我遇到的问题是,如果我调用那个 API 部分,我会收到错误:
信息:承载未通过身份验证。失败消息:没有可用于令牌的 SecurityTokenValidator:
任何帮助将不胜感激,因为我找不到错误
【问题讨论】:
你可以试试这个link 感谢您的回答。不幸的是,我不使用 OpenID Connect 没有“普通”的方式来完成这个吗? 在声明列表中使用ClaimTypes.Role
而不是 "roles"
。 rolesString
的内容是什么?
感谢您的回答。 rolesString的内容是一个List如果您想添加角色作为声明,请尝试使用ClaimTypes.Role
而不是roles
。
var tokeOptions = new JwtSecurityToken(
issuer: "http://localhost:44352",
audience: "http://localhost:44352",
claims: new List<Claim>(new List<Claim>
new Claim("userName",cred.userName),
new Claim(ClaimTypes.Role, "Admin")
),
expires: DateTime.Now.AddHours(1),
signingCredentials: signinCredentials
);
【讨论】:
感谢您的回答。不幸的是,这并没有做到。我仍然遇到同样的错误 当我用 postman 测试时,它在我的 asp.net core 2.2 项目中运行良好。你如何测试 api? 我正在使用我正在开发的 Angular7 SPA 进行测试【参考方案2】:感谢邹星,我找到了错误的根源。问题是我用引号发送了不记名令牌。
现在API中的错误消失了,问题是现在API中的授权失败并返回403。
编辑:
我发现了有关错误 403 的问题。似乎您只能在承载令牌中发送一个角色以供 ASP.Net 验证它。 userManager.GetRolesAsync 的返回类型表明用户可以拥有多个角色,这些角色可以包含在 JWT 不记名令牌中。
这意味着我的问题已解决。
我要感谢大家的回答。没有你,我不会得到它!
【讨论】:
【参考方案3】:我是这样处理这个问题的:
client.DefaultRequestHeaders.Add("Authorization", $"Bearer token.Replace("\"", "")");
不是最好的解决方案,但确实有效。
【讨论】:
以上是关于ASP.Net Core 3.0 JWT Bearer Token 没有 SecurityTokenValidator 可用的主要内容,如果未能解决你的问题,请参考以下文章