ASP.Net Core 3 API 总是返回 401- JwtBearer
Posted
技术标签:
【中文标题】ASP.Net Core 3 API 总是返回 401- JwtBearer【英文标题】:ASP.Net Core 3 API always returns 401- JwtBearer 【发布时间】:2020-05-27 09:26:05 【问题描述】:我有一个 ASP .NET Core WebAPI,我生成了一个 JWT 令牌用于授权,但每当我发送请求时,我都会收到 401 - Unauthorized。
操作顺序:
1. GET for token
2. GET for user <-- 401
我在 jwt.io 上检查了我的令牌,它是正确的。 当我删除 [Authorize] 属性时一切正常
Startup.cs
public void ConfigureServices(IServiceCollection services)
IdentityModelEventSource.ShowPII = true;
var appSettingsSection = Configuration.GetSection("Jwt");
services.Configure<JwtSettings>(appSettingsSection);
var appSettings = appSettingsSection.Get<JwtSettings>();
services.AddControllers();
services.AddOptions();
services.AddAuthentication(x =>
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(x=>
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateLifetime = true,
ValidAudience = appSettings.Issuer,
ValidIssuer = appSettings.Issuer,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Key))
;
);
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
);
CreateToken 方法
public JwtDto CreateToken(string email, string role)
var now = DateTime.UtcNow;
var claims = new Claim[]
new Claim(JwtRegisteredClaimNames.Sub,email),
new Claim(ClaimTypes.Role, role),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat,now.ToTimestamp().ToString(),ClaimValueTypes.Integer64)
;
var expires = now.AddMinutes(360);
var singingCredentails = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_settings.Key)),SecurityAlgorithms.HmacSha256);
var jwt = new JwtSecurityToken(
issuer: _settings.Issuer,
claims: claims,
notBefore: now,
expires: expires,
signingCredentials: singingCredentails
);
var token = new JwtSecurityTokenHandler().WriteToken(jwt);
return new JwtDto
Token = token,
Expiry = expires.ToTimestamp()
;
GetToken - API
[HttpGet]
[Route("token")]
public IActionResult GetToken()
var token = _jwtHandler.CreateToken("test", "user");
return Json(token);
GetUser - API
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpGet("email")]
public async Task<UserDto> Get(string email)
return await _userService.GetUserAsync(email);
【问题讨论】:
您知道您对 GetUser 的调用有一个格式正确的 Authorization 标头,其中包含令牌? "授权:承载我遇到了完全相同的问题,并且认为问题出在 Startup.cs 中的 Configure() 方法中。您有正确的 UseAuthentication() 和 UseAuthorization() 调用,顺序正确,这很重要,也是我发现的问题。因此,对您而言,我认为问题在于缺少 UseCors() 调用。我的工作启动类如下:
public class Startup
private bool _isDevelopmentEnvironment = true;
public IConfiguration configuration get;
public Startup(IConfiguration configuration)
this.configuration = configuration;
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
services.AddControllers();
// Retrieve App Settings:
var appSettingsSection = configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
var appSettings = appSettingsSection.Get<AppSettings>();
// Configure JWT:
var key = Encoding.ASCII.GetBytes(appSettings.JwtSharedSecret);
services.AddAuthentication(x =>
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(x =>
x.RequireHttpsMetadata = !_isDevelopmentEnvironment;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = appSettings.JwtValidateIssuer,
ValidateAudience = appSettings.JwtValidateAudience,
ValidateLifetime = appSettings.JwtValidateLifetime,
ClockSkew = TimeSpan.Zero
;
);
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IUserService, UserService>();
services.AddScoped<IHydrator<User, UserModel>, UserModelHydrator>();
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
_isDevelopmentEnvironment = false;
app.UseHsts();
app.UseHttpsRedirection();
app.UseRouting();
// TODO: Adjust CORS settings appropriately
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllers();
);
我还确认令牌生成代码和 Startup.cs 代码都使用应用程序设置中的相同密钥,我看不出您是如何在 CreateToken() 方法中获得它的,但我假设它来自相同的设置文件。希望这会有所帮助!
【讨论】:
以上是关于ASP.Net Core 3 API 总是返回 401- JwtBearer的主要内容,如果未能解决你的问题,请参考以下文章
每当我发送包含 Bearer 令牌的请求时,ASP.Net Core API 总是返回 401 未授权
IFormFile 在 asp.net core 2.1 中总是返回 null
ASP.NET Core Identity 3.1:UserManager.RemoveFromRoleAsync 总是返回 UserNotInRole
Blazor ASP.Net Core 3.1 Web API 在发布时返回 404 错误
ASP.NET Core 3.1 MVC JWT 登录返回 401
在 HTTPS 上使用 Windows 身份验证首次调用 ASP.NET Core 2.0 Web API 在 Chrome 中总是失败