我试图返回一个更改的标题,如果用户发送的令牌已过期,以便我可以重新发送我的刷新令牌,如果它已过期。
我正在使用.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(当我检查它时,它是“Token-Expired”)。
最后,这是一个失败的请求后Postman的截图,所以响应正在发送,但没有在我的JS中收到。
关于为什么我的标题不符合我在javascript中的响应的任何想法?
在通过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.令牌过期并获得刷新令牌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;
}
};
});
现在,您将在客户端得到回复。希望你能找到你的解决方案。如有任何疑问,请告诉我。