为什么 CORS 错误 "Response to preflight request doesn't pass access control check"?

Why CORS error "Response to preflight request doesn't pass access control check"?

我在我的项目中使用具有 OAuth 授权的 ASP.NET Web API。

我尝试使用最佳实践来解耦解决方案中的每一层。 我有一个 Web 项目,其中包含 AngularJS 上传到 www.example.com 的文件和其他资源,我还有另一个受保护的后端 Web api 控制器和上传到 api 的服务器端内容的项目 api.example.com

在本地主机上一切正常。当我将此发布到生产服务器时,对“/token”的请求成功但请求后端任何控制器中的任何操作 api returns 此错误: "Access to XMLHttpRequest at 'http://api.example.com/someRoute' from origin 'http://www.example.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.".

我在互联网上搜索了几乎所有活跃的 link 类似错误,但我还没有找到答案!

我从后端API粘贴了一些我的代码,这样你可以更好地理解我的方法。

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {

        HttpConfiguration httpConfig = new HttpConfiguration();

        UnityConfig.Register(httpConfig);

        ConfigureAuth(app);

        WebApiConfig.Register(httpConfig);

        app.UseWebApi(httpConfig);

        #region AutoMapper Init
        DtoMapping.Map();
        #endregion
    }
}


public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the auth context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(AuthContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            //remove this line on production
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
            Provider = new SimpleAuthorizationServerProvider()
        };

        // Token Generation
        app.UseOAuthBearerTokens(OAuthServerOptions);
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }

public class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(cors);

        config.MapHttpAttributeRoutes();

        //...
    }
}

[EnableCors("*", "*", "*")]
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
        return Task.FromResult<object>(null);
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        IList<string> roleNames;
        using (var _repo = new IdentityRepository())
        {
            var user = await _repo.FindUserAsync(context.UserName, context.Password);
            if (user == null)
            {
                context.SetError("invalid_grant", "username or password is invalid.");
                context.Rejected();
                return;
            }

            roleNames = await _repo.GetRolesForUserAsync(user.Id);
        }

        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        foreach (var roleName in roleNames)
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, roleName));
        }

        var props = new AuthenticationProperties(new Dictionary<string, string>
            {
                {
                    "userName", context.UserName
                }
            });

        var ticket = new AuthenticationTicket(identity, props);
        context.Validated(ticket);

    }
}

那么,有人能帮帮我吗?

感谢您的宝贵时间。

如果有人想知道,我就是这样解决这个问题的:

这不是关于不在 asp.net web api 中设置 cors 策略(正如我提到的,我按照 Microsoft docs website 的建议做了。)

问题是 IIS 没有配置为处理 OPTION 动词方法! 并且由于飞行前请求使用的是 OPTION 方法,它总是找不到 404(来自 Web 服务器的拒绝),因此出现错误。

我应该提一下,直到今天我仍然不知道为什么“/token”在配置网络服务器之前起作用,为什么控制器没有同样的反应!

不过好歹问题就这么解决了。 希望对您有所帮助!

可能有点旧但值得一提的是你需要在 global.asax

中添加 cors headers
protected void Application_BeginRequest(object sender, EventArgs e)
{
    var context = System.Web.HttpContext.Current;
    var origins = System.Configuration.ConfigurationManager.AppSettings["AllowedCorsDomain"]?.TrimEnd('/');
    context.Response.AddHeader("Access-Control-Allow-Origin", origins);

    if (context.Request.HttpMethod == "OPTIONS")
    {
        //These headers are handling the "pre-flight" OPTIONS call sent by the browser
        context.Response.AddHeader("Access-Control-Allow-credentials", "true");
        context.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, POST, DELETE, OPTIONS");
        context.Response.AddHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type, origin, authorization, Accepts, accept, client-security-token, access-control-allow-headers");
        context.Response.AddHeader("Access-Control-Max-Age", "86400");
        context.Response.End();
    }
}