Scr*_*ler 1 authentication http-status-code-401 jwt asp.net-core
我遇到了 .NET Core 如何在我的生产环境中处理 JSON Web 令牌 (JWT) 身份验证的问题。我正在使用 Postman 进行测试。如果我使用有效的令牌调用我的 API,它可以正常工作并从 API 端点返回预期的响应。但是,如果令牌已过期,我将不会收到预期的 HTTP 401。事实上,我没有收到任何响应,它只是悄悄地失败了。我的生产配置似乎不起作用。如果我在本地开发环境中对此进行测试,我不会遇到任何问题,并且过期的令牌会像预期的那样获得 401 未授权的 HTTP 响应。
我的 Web 应用程序对通过网站登录的人使用 cookie 身份验证,对连接到 API 的人使用 JWT 身份验证。这是 JWT 身份验证的配置。这是在 Startup.cs 中。这是 services.Authentication 的 JWT 配置部分。cookie 身份验证首先设置并且是默认身份验证方案。
.AddJwtBearer(options =>{
options.RequireHttpsMetadata = !_hostingEnvironment.IsDevelopment();
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Settings.Api.JwtBearer.TokenValidation.ValidIssuer,
ValidAudience = Settings.Api.JwtBearer.TokenValidation.ValidAudience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Settings.Api.JwtBearer.TokenValidation.IssuerSigningKey))
};
options.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json; charset=utf-8";
var message = _hostingEnvironment.IsDevelopment() ? context.Exception.ToString() : "An error occurred processing your authentication.";
var result = JsonConvert.SerializeObject(new { message });
return context.Response.WriteAsync(result);
}
};});
Run Code Online (Sandbox Code Playgroud)
这是 Startup.cs 中的其他相关配置:
public void Configure(IApplicationBuilder app, IHostingEnvironment env){
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error/Exception");
app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseHsts();
app.UseHttpsRedirection();
}
app.UseStaticFiles();
app.UseCors(Constants.Security.Cors.PolicyName);
app.UseAuthentication();
app.UseMvc(ConfigureRoutes);}
Run Code Online (Sandbox Code Playgroud)
` 我已经使用了很多配置设置并在生产中进行了测试,但是当令牌身份验证失败时,我总是最终没有响应。由于它在我的本地开发环境中运行良好,这一定意味着我的生产配置有问题,但我很困惑,没有想法。有关更多信息,请参阅错误日志中的错误示例:
信息:Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1] 未能验证令牌。Microsoft.IdentityModel.Tokens.SecurityTokenExpiredException:IDX10223:生命周期验证失败。令牌已过期。ValidTo: '[PII is hidden]', 当前时间: '[PII is hidden]'。在 Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(Nullable
1 notBefore, Nullable1 expires, SecurityToken securityToken, TokenValidationParameters validationParameters) 在 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateLifetime(Nullable1 notBefore, Nullable1 过期, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters) 在 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters) 在 System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(Parameter token validationTokens)在 Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.d__6.MoveNext() 信息:Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7] Bearer 未经过身份验证。失败消息:IDX10223:生命周期验证失败。令牌已过期。ValidTo: '[PII is hidden]', 当前时间: '[PII is hidden]'。信息:Microsoft.AspNetCore.Authorization。DefaultAuthorizationService[2] 授权失败。信息:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3] 过滤器“Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter”处的请求授权失败。信息:Microsoft.AspNetCore.Mvc.ChallengeResult[1] 使用身份验证方案(Bearer)执行 ChallengeResult。信息:Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 在 109.4625 毫秒内执行操作 Web.Controllers.ApiController.Users (Web) 信息:Microsoft.AspNetCore.Routing.EndpointMiddleware[1] 执行端点'Web.Controllers.ApiController.用户 (Web)' 失败:Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1] 执行请求时发生未处理的异常。System.InvalidOperationException: 无法设置 StatusCode,因为响应已经开始。在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value) 在 Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode (Int32 值)在 Microsoft.AspNetCore.Http.Internal.DefaultHttpResponse.set_StatusCode(Int32 值)在 Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.d__7.MoveNext()
预先感谢您提供有关如何解决此问题的任何想法。
所以我找到了一个部分解决方案,至少可以解除我的阻塞,这样我就可以继续我的 API 开发。尝试更改 JwtBearerEvents OnAuthenticationFailed 中的 context.Response 在我的生产环境中不起作用(尽管它在我的本地机器上运行良好)。我尝试了很多变体,但最后唯一有效的是从 Startup.cs 中删除整个代码块:
options.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = context =>
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
context.Response.ContentType = "application/json; charset=utf-8";
var message = _hostingEnvironment.IsDevelopment() ? context.Exception.ToString() : "An error occurred processing your authentication.";
var result = JsonConvert.SerializeObject(new { message });
return context.Response.WriteAsync(result);
}
};
Run Code Online (Sandbox Code Playgroud)
一旦我这样做了,在 Postman 中进行测试时,我开始获得 401 代码用于失败的令牌验证,这是一件好事和预期的行为。但是,在响应正文中,也返回了默认错误页面 HTML。
为了解决这个问题,我不得不修改 Startup.cs 中的 Configure 方法,以便 UseStatusCodePagesWithReExecute 忽略 API:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error/Exception");
app.UseWhen(context => !context.Request.Path.Value.StartsWith("/api"), builder =>
{
builder.UseStatusCodePagesWithReExecute("/Error/{0}");
});
app.UseHsts();
app.UseHttpsRedirection();
}
app.UseStaticFiles();
app.UseCors(Constants.Security.Cors.PolicyName);
app.UseAuthentication();
app.UseMvc(ConfigureRoutes);
}
Run Code Online (Sandbox Code Playgroud)
这有效,但我不喜欢它。感觉像一个黑客。现在我得到 401 失败的令牌身份验证,并且正文中没有任何内容。就像我之前提到的那样,这解除了我的封锁,但我仍然希望通过响应返回自定义错误消息。
所以,我的下一个问题是,如果我不能使用 JwtBearerEvents OnAuthenticationFailed 添加消息,那么添加错误消息的正确位置在哪里?
| 归档时间: |
|
| 查看次数: |
7225 次 |
| 最近记录: |