为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将正常工作:
- 从您的API中删除任何代码,如
config.EnableCors(), [EnableCors(header:"*"....)]
。 -
转到startup.cs并添加以下行
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
之前
ConfigureAuth(app);
您还需要安装Microsoft.owin.cors包才能使用此function
- Identity 2.0:创建自定义ClaimsIdentity例如:User.Identity.GetUserById (int id)for Per Request Validation
- 用于在MVC5中模拟ConfirmEmailAsync和其他UserManager方法的接口
- 没有Owin的Asp.Net MVC 5?
- 实体类型ApplicationUser不是当前上下文的模型的一部分
- 找不到类型或命名空间名称“System”
- MVC – 混合身份validation – OWIN + Windows身份validation
- 将所有区域,控制器和动作作为树
- 使用MVC 5 RouteArea属性时,无法找到默认区域视图
- 了解MVC-5身份