对于那些对答案和上一个答案感到好奇的人,它确实与排序密切相关。每当您添加 Owin 中间件时,请务必注意:注册顺序是必不可少的。
app.useCors(Microsoft.Owin.Cors.CorsOptions.AllowAll)
将此作为您的身份验证文件中的第一件事,基本上是在到达您的 OAuthServer 和 Web Api 之前注册 Cors 处理程序。
在 OAuth 之后移动它会产生相反的效果,因此需要在 GrantResourceOwnerCredentials 中添加 Access-Control-Allow-Origin 标头。
要回答另一个问题,如果您从浏览器发送 CORS 请求并且指定了 CorsOptions.AllowAll,则标头已经存在的原因,它会为您添加一个,因此当它到达 /token 端点时它已经添加了一个 OAuth 服务器。 (仅表示在 http 请求中找到了一个,并且您允许所有来源)。
您可以相应地验证行为,
在 Fiddler 中,使用包含任意值的 Origin 标头向您的 Token 端点发送一个新请求。在您的 OAuth 服务器上的 GrantResourceOwnerCredentials 中放置一个断点,然后检查 context.Response.Headers,它现在将包含您传入的来源。(请记住,浏览器必须检查它,fiddler 会高兴一整天)
如果您随后告诉 CORS 不要使用 CorsOptions.AllowAll 并将 AllowAnyOrigin 设置为 false,您会注意到从 Fiddler 发送的 Origin 不再添加到响应标头中。
浏览器反过来会拒绝 CORS 请求,因为没有返回源 - 在 Access-Control-Allow-Origin 标头中找不到源“”。
现在是重要的一点:
如果您设置 CorsOptions.AllowAll,它会完全按照它所说的去做,允许 CORS 请求在 Owin 管道中注册 CORS 之后发生的任何中间件上的任何方法,因此请确保这是您打算做的。 IE:如果您先注册 CORS,然后再注册 OAuth 和 Web API,那么如果您没有显式添加代码\属性来阻止它,那么您的所有 Web API 方法都可以通过 CORS 访问。
如果你想限制方法然后实现 ICorsPolicyProvider,部分来自http://katanaproject.codeplex.com/(Microsoft.Owin.Cors)
public class MyCorsPolicyProvider : ICorsPolicyProvider
{
public Task<CorsPolicy> GetCorsPolicyAsync(IOwinRequest request)
{
// Grant Nothing.
var policy = new CorsPolicy
{
AllowAnyHeader = false,
AllowAnyMethod = false,
AllowAnyOrigin = false,
SupportsCredentials = false
};
// Now we can get a bit clever: (Awesome, they requested the token endpoint. Setup OAuth options for that.
if (OAuthOptions.TokenEndpointPath.HasValue && OAuthOptions.TokenEndpointPath == request.Path)
{
// Hypothetical scenario, tokens can only be obtained using CORS when the Origin is http://localhost
policy.AllowAnyHeader = true;
policy.AllowAnyMethod = true;
policy.AllowAnyOrigin = false;
policy.SupportsCredentials = true;
policy.Origins.Add("http://localhost");
return Task.FromResult(policy);
}
// No token?, must already have one.... so this must be a WebApi request then.
// From here we could check where the request is going, do some other fun stuff etc... etc...
// Alternatively, do nothing, set config.EnableCors() in WebApi, then apply the EnableCors() attribute on your methods to allow it through.
return null; }
}
返回空值;告诉 Owin 继续到下一个中间件并允许请求通过但没有策略因此 NO CORS!,允许您在 WebAPI 中设置适当的 CORS 属性
现在非常重要的一点,如果 Access-Control-Allow-Origins 标头不存在,请不要将其添加到您的响应中,除非这确实是您想要的,因为这取决于您的中间件注册顺序,它将打开所有除非您在其他地方明确阻止它们或删除标头,否则 CORS 请求的大门,当您尝试将 CORS 与 WebApi 一起使用并想要限制它时,基本上会导致很多问题。
要在其他地方阻止它们,您可以为 WebApi 添加一个 CorsPolicyProvider (System.Web.Http),然后在 Owin 中设置一个 Context 变量,一旦请求到达 WebApi,您就可以读取该变量。
public class WebApiCorsPolicyProvider : System.Web.Http.Cors.ICorsPolicyProvider
{
public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var policy = new CorsPolicy
{
AllowAnyHeader = false,
AllowAnyMethod = false,
AllowAnyOrigin = false,
SupportsCredentials = false
};
// The benefit of being at this point in the pipeline is we have been authenticated\authorized so can check all our claims for CORS purposes too if needed and set errors etc...
// In an Owin pipeline?
var owinContext = request.GetOwinContext();
if (owinContext != null)
{
// We have an owin pipeline, we can get owin parameters and other things here.
}
else
{
// Write your code here to determine the right CORS options. Non Owin pipeline variant.
}
return Task.FromResult(policy);
}
}
最后,向下传播到 WebApi CORS 策略提供程序的另一个好处是,此时将进行授权,因此您可以在该阶段在 CORS 策略提供程序中应用额外的 Origin 过滤器。