返回响应头 OnAuthenticationFailed
Posted
技术标签:
【中文标题】返回响应头 OnAuthenticationFailed【英文标题】:Returning response header OnAuthenticationFailed 【发布时间】:2019-09-18 09:54:11 【问题描述】:如果用户发送的令牌已过期,我将尝试返回更改后的标头,以便在过期时重新发送我的刷新令牌。
我正在使用带有“进程内”托管的 .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()
,我可以看到计数 = 1(当我检查它时,它是“令牌过期”)。
最后,这是 Postman 在请求失败后的屏幕截图,因此响应正在发送,但在我的 JS 中没有收到。
关于为什么我的标头不符合我在 javascript 中的响应的任何想法?
【问题讨论】:
【参考方案1】:当您在 CORS 上使用 Fetch API 时,访问响应标头会受到限制。由于此限制,您只能访问以下标准标头:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
参考:https://***.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");
这样您就可以使用 Fetch API over CORS 从客户端访问自定义标头。
【讨论】:
嗨@NanYu,我只希望在身份验证失败时返回该响应。不是每个请求 @thalacker ,您只是在OnAuthenticationFailed
事件中添加Token-Expired作为标头值,以满足您的要求。【参考方案2】:
我在这里描述两者 - 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;
;
);
现在,您将在客户端收到响应。 希望你能找到你的解决方案。如有任何疑问,请告诉我。
【讨论】:
以上是关于返回响应头 OnAuthenticationFailed的主要内容,如果未能解决你的问题,请参考以下文章
HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码
HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码