我正在尝试确定为什么/如何在响应为401-Unauthorized时丢失'Access-Control-Allow-Origin'标头。
我正在使用基于令牌的身份验证,其中令牌具有到期日期。当此令牌过期时,服务器将返回401未授权的,但在chrome(以及IE和FF)中,它永远不会看到Allow Origin标头和错误以及通常的CORS错误:XMLHttpRequest cannot load http://my.rest.service. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
我不确定这些是否相关,因为auth逻辑工作正常,只是当响应为401时CORS会窒息。
namespace NViewREST.Handlers
{
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Handler for processing Cross Origin Resource Sharing (CORS) requests
/// </summary>
public class CorsHandler : DelegatingHandler
{
/// <summary>The origin.</summary>
private const string Origin = "Origin";
/// <summary>Header indicating we should treat this is CORS request.</summary>
private const string EnableCors = "X-EnableCors";
/// <summary>The access control request method.</summary>
private const string AccessControlRequestMethod = "Access-Control-Request-Method";
/// <summary>The access control request headers.</summary>
private const string AccessControlRequestHeaders = "Access-Control-Request-Headers";
/// <summary>The access control allow origin.</summary>
private const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
/// <summary>The access control allow methods.</summary>
private const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
/// <summary>The access control allow headers.</summary>
private const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
/// <summary>
/// send async request
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The <see cref="Task"/>.</returns>
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// if it has our NFIB enable CORS header or has the access control request method header, we're assuming CORS request
var isCorsRequest = request.Headers.Contains(AccessControlRequestMethod) || request.Headers.Contains(EnableCors);
// preflight == OPTIONS request - usually only sent prior to CORS requests
var isPreflightRequest = request.Method == HttpMethod.Options;
// express exit if its a normal request
if (!isCorsRequest)
{
return base.SendAsync(request, cancellationToken);
}
// actual CORS request - add appropriate header before executing as normal
if (!isPreflightRequest)
{
return base.SendAsync(request, cancellationToken).ContinueWith(
t =>
{
var resp = t.Result;
resp.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
return resp;
},
cancellationToken);
}
// at this point its the preflight request - add headers to indicate allowed origins
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Headers.Add(AccessControlAllowOrigin, request.Headers.GetValues(Origin).First());
// add header to indicate allowed methods
var accessControlRequestMethod = request.Headers.GetValues(AccessControlRequestMethod).FirstOrDefault();
if (accessControlRequestMethod != null)
{
response.Headers.Add(AccessControlAllowMethods, accessControlRequestMethod);
}
// add headers to indicate allowed headers
var requestedHeaders = string.Join(", ", request.Headers.GetValues(AccessControlRequestHeaders));
if (!string.IsNullOrEmpty(requestedHeaders))
{
response.Headers.Add(AccessControlAllowHeaders, requestedHeaders);
}
// send result of OPTIONS request
var tcs = new TaskCompletionSource<HttpResponseMessage>();
tcs.SetResult(response);
return tcs.Task;
}
}
}
我可以单步执行添加标题的行,即使响应是401,所以我知道.net端正在添加它。
function executeAjax (method, url, data, token) {
url = (url.indexOf('/') === 0) ? url : "/" + url;
var options = {
method: method,
url: app.settings.apiUrlRoot + url,
data: data
};
token = token || localStorage.getItem("sessionKey");
options.headers = {
"Accept": "application/json",
//header for enabling CORS
"X-EnableCors": 'true'
}
if (token !== undefined && token !== null)
{
options.headers["X-ADAuth"] = token,
}
return $.ajax(options);
};
此调用的结果是我之前引用的CORS错误。
我知道防火墙或中间件剥离这些问题没有问题,因为任何其他非401 ajax请求执行得很好。
为什么标题消失了?
答案 0 :(得分:2)
我有完全相同的问题,并通过在返回之前将401 CORS标头添加到401响应来解决它。
var response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Bearer", "errorMessage"));
response.Headers.Add(AccessControlAllowOrigin, "*");
return response;