為 Web Api 2 和 OWIN 令牌身份驗證啟用 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); ... }令牌配置
public static void ConfigureOAuth(IAppBuilder app) { app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<AppUserManager>(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()); }授權提供者
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); var appUserManager = context.OwinContext.GetUserManager<AppUserManager>(); 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 }身份配置
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> 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<AppUser>(context.Get<ApplicationDbContect>())); ... var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<AppUser>(dataProtectionProvider.Create("ASP.NET Identity")); } return manager; }編輯:
1. 重要說明是直接打開端點(localhost:82/token)可以。
2. 從 webproject 呼叫 Api (localhost:82/api/..) 也可以,因此為 WebApi 啟用了 CORS。
我知道您的問題已在評論中解決,但我認為了解導致問題的原因以及如何解決這一類問題很重要。
查看您的程式碼,我可以看到您
Access-Control-Allow-Origin為 Token 端點多次設置標頭: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後ConfigureOAuth允許您的 CORS 標頭僅設置一次(因為 owin 管道在 OAuth 中間件處中斷,並且永遠不會到達Token端點的 Microsoft CORS 中間件)並使您的 Ajax 呼叫正常工作。為了獲得更好的全域解決方案,您可以嘗試
app.UseCors在 OAuth 中間件呼叫之前再次放置,並刪除內部的第二個Access-Control-Allow-Origin插入GrantResourceOwnerCredentials。