返回响应头 OnAuthenticationFailed

tha*_*ker 2 javascript c# api http-headers asp.net-core

如果用户发送的令牌已过期,我将尝试返回更改的标头,以便我可以在它过期时重新发送我的刷新令牌。

我将 .NET Core 2.2 与“In-Process”托管一起使用,这很重要。

这是我ConfigureServices从我的Startup.cs.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "bearer";
    options.DefaultChallengeScheme = "bearer";
}).AddJwtBearer("bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["serverSigningPassword"])),
        ValidateLifetime = true,
        ClockSkew = System.TimeSpan.Zero //the default for this setting is 5 minutes
    };
    options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return System.Threading.Tasks.Task.CompletedTask;
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

然后当我尝试使用以下内容从 javascript 获取“授权”端点时。

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "bearer";
    options.DefaultChallengeScheme = "bearer";
}).AddJwtBearer("bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["serverSigningPassword"])),
        ValidateLifetime = true,
        ClockSkew = System.TimeSpan.Zero //the default for this setting is 5 minutes
    };
    options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return System.Threading.Tasks.Task.CompletedTask;
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

此图像来自将鼠标悬停在标题上。它肯定会达到我的断点(因为context.Response.Headers.Add()我可以看到计数 = 1(当我检查它时,这是“令牌过期”)。

在此处输入图片说明

最后,这是请求失败后 Postman 的屏幕截图,因此响应正在发送,但未在我的 JS 中接收。 在此处输入图片说明

关于为什么我的标题没有坚持我在 javascript 中的响应的任何想法?

Nan*_* Yu 5

当您通过 CORS 使用 Fetch API 时,访问响应标头存在限制。由于此限制,您只能访问以下标准标头:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

参考:https : //stackoverflow.com/a/44816592/5751404

因此,在客户端访问自定义标头的一种方法是将标头添加access-control-expose-headers到响应中,并使用逗号分隔的标头:

services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
    builder.AllowAnyOrigin()
          .AllowAnyMethod()
          .AllowAnyHeader()
          .WithExposedHeaders("Token-Expired"); ;
}));
Run Code Online (Sandbox Code Playgroud)

Configure

app.UseCors("MyPolicy");
Run Code Online (Sandbox Code Playgroud)

这样您就可以使用 Fetch API over CORS 从客户端访问自定义标头。