返回响应头OnAuthenticationFailed

时间:2019-04-29 18:34:28

标签: javascript c# api asp.net-core http-headers

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

我将.NET Core 2.2与“进程内”托管一起使用,以防万一。

这是我的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;
        }
    };
});

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

async function fetchWithCredentials(url, options) {    
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);
    if (response.ok) { //all is good, return the response
        return response;
    }

    console.log(response.headers) //nothing in this array

    // it will never do this "if" statement because there are no headers
    if (response.status === 401 && response.headers.has('Token-Expired')) {
        // refresh the token
        return await fetchWithCredentials(url, options); //repeat the original request
    } else { //status is not 401 and/or there's no Token-Expired header
        return response; 
    }
}

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

enter image description here

最后,这是请求失败后来自Postman的屏幕截图,因此响应正在发送,但未在我的JS中接收。 enter image description here

关于我的标头为何不坚持我在javascript中的响应的任何想法?

2 个答案:

答案 0 :(得分:0)

使用基于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"); ;
}));

Configure中:

app.UseCors("MyPolicy");

因此您可以使用基于CORS的Fetch API从客户端访问自定义标头。

答案 1 :(得分:0)

我在此同时描述- 1.令牌过期并获得刷新令牌 2.仅用于未经授权的请求。

async function fetchWithCredentials(url, options) {    
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);//this is a function for get a response. I didn't explain it here. Hope you understand. 
    if (response.ok) {
        return response;
    }

    let flag:boolean=false; //set flag for executing one if statement at a time.

if (response.status == 401 && response.headers.has('Token-Expired')) {
        // refresh the token
        flag=true;  //set flag true.
        //write something as per your requirement.
    } 

if (response.status == 401 && flag==false) {
        **// Only for unauthorized request. You can use this for your problem.**
        //write something as per your requirement.
    } 
}

最重要的是,您必须在startup.cs中使用以下代码。

services.AddCors(context => context.AddPolicy("CustomPolicy", builder =>
{
    builder.AllowAnyOrigin()
          .AllowAnyMethod()
          .AllowAnyHeader()
          .WithExposedHeaders("Token-Expired"); ;
}));

在“配置”中:

app.UseCors("CustomPolicy");

并按原样使用以下代码。

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;
        }
    };
});

现在,您将在客户端得到响应。 希望您能找到解决方案。如有任何疑问,请让我知道。