为Web Api 2和OWIN令牌身份validation启用CORS

我有一个ASP.NET MVC 5 webproject(localhost:81),它使用Knockoutjs从我的WebApi 2项目(localhost:82)调用函数,以便在我启用CORS的两个项目之间进行通信。 到目前为止,一切都有效,直到我尝试对WebApi实现OWIN令牌认证。

要在WebApi上使用/ token端点,我还需要在端点上启用CORS,但经过几个小时的尝试和搜索解决方案后,它仍在运行,并且api / token仍然会导致:

XMLHttpRequest cannot load http://localhost:82/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. public void Configuration(IAppBuilder app) { app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); TokenConfig.ConfigureOAuth(app); ... } 

TokenConfig

 public static void ConfigureOAuth(IAppBuilder app) { app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext(AppUserManager.Create); OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() { AllowInsecureHttp = true, TokenEndpointPath = new PathString("/token"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), Provider = new SimpleAuthorizationServerProvider() }; app.UseOAuthAuthorizationServer(OAuthServerOptions); app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); } 

AuthorizationProvider

 public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); var appUserManager = context.OwinContext.GetUserManager(); IdentityUser user = await appUserManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The user name or password is incorrect."); return; } ... claims } 

IdentityConfig

 public static AppUserManager Create(IdentityFactoryOptions options, IOwinContext context) { // Tried to enable it again without success. //context.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"}); var manager = new AppUserManager(new UserStore(context.Get())); ... var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); } return manager; } 

编辑:

1.重要提示是直接打开端点(localhost:82 / token)。

2.从webproject调用Api(localhost:82 / api / ..)也可以,因此为WebApi启用了CORS。

我知道你的问题在评论中得到了解决,但我认为重要的是要了解导致它的原因以及如何解决这一类问题。

查看您的代码,我可以看到您为Token端点多次设置Access-Control-Allow-Origin标头:

 app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

GrantResourceOwnerCredentials方法中:

 context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

考虑到CORS规范 ,这本身就是一个问题,因为:

如果响应包含零个或多个Access-Control-Allow-Origin标头值,则返回失败并终止此算法。

在您的方案中,框架将设置此标头两次,并了解必须如何实现CORS,这将导致在某些情况下删除标头(可能与客户端相关)。

以下问题答案也证实了这一点: Duplicate Access-Control-Allow-Origin:*导致COR错误?

因此,在调用app.UseCors之后将调用移动到app.UseCors允许您的CORS标头只设置一次(因为owin管道在OAuth中间件中被中断,并且永远不会到达Token端点的Microsoft CORS中间件)并且使得你的Ajax调用工作。

要获得更好的全局解决方案,您可以尝试在OAuth中间件调用之前再次app.UseCors ,并在GrantResourceOwnerCredentials删除第二个Access-Control-Allow-Origin插入。

按照以下步骤操作,您的API将正常工作:

  1. 从您的API中删除任何代码,如config.EnableCors(), [EnableCors(header:"*"....)]
  2. 转到startup.cs并添加以下行

     app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

之前

  ConfigureAuth(app); 

您还需要安装Microsoft.owin.cors包才能使用此function