IdentityServer3 - 因无效的CORS路径而被拒绝

32

我们有一个ASP.NET MVC应用程序,它与IdentityServer3进行身份验证没有问题,但是使用ApiController的Web API部分在用户等待大约三分钟后(在3分钟之前,一切似乎都很好)开始失败。

在Chrome中看到的错误如下:

XMLHttpRequest无法加载https://test-auth.myauthapp.com/auth/connect/authorize?client_id=ecan-farmda…gwLTk5ZjMtN2QxZjUyMjgxNGE4MDg2NjFhZTAtOTEzNi00MDE3LTkzNGQtNTc5ODAzZTE1Mzgw。 请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,“http://test.myapp.com”的来源不被允许访问。

在IE中,我收到以下错误:

SCRIPT7002:XMLHttpRequest:网络错误0x4c7,操作被用户取消。

我查看IdentityServer3的日志,发现有如下记录:

2015-08-10 16:42 [警告] (Thinktecture.IdentityServer.Core.Configuration.Hosting.CorsPolicyProvider) 来自源http://test.myapp.com 的路径为/connect/authorize的CORS请求被拒绝,因为CORS路径无效。

在IdentityServer3 Web应用程序中,我正在为客户端提供AllowedCorsOrigins:

Thinktecture.IdentityServer.Core.Models.Client client = new Thinktecture.IdentityServer.Core.Models.Client()
{
    Enabled = configClient.Enabled,
    ClientId = configClient.Id,
    ClientName = configClient.Name,
    RedirectUris = new List<string>(),
    PostLogoutRedirectUris = new List<string>(),
    AllowedCorsOrigins = new List<string>(),
    RequireConsent = false, // Don't show consents screen to user
    RefreshTokenExpiration = Thinktecture.IdentityServer.Core.Models.TokenExpiration.Sliding
};

foreach (Configuration.RegisteredUri uri in configClient.RedirectUris)
{
    client.RedirectUris.Add(uri.Uri);
}

foreach (Configuration.RegisteredUri uri in configClient.PostLogoutRedirectUris)
{
    client.PostLogoutRedirectUris.Add(uri.Uri);
}

// Quick hack to try and get CORS working
client.AllowedCorsOrigins.Add("http://test.myapp.com");
client.AllowedCorsOrigins.Add("http://test.myapp.com/"); // Don't think trailing / needed, but added just in case

clients.Add(client);

当注册服务时,我添加了一个InMemoryCorsPolicyService:

app.Map("/auth", idsrvApp =>
{
    var factory = new IdentityServerServiceFactory();

    factory.Register(new Registration<AuthContext>(resolver => AuthObjects.AuthContext));
    factory.Register(new Registration<AuthUserStore>());
    factory.Register(new Registration<AuthRoleStore>());
    factory.Register(new Registration<AuthUserManager>());
    factory.Register(new Registration<AuthRoleManager>());

    // Custom user service used to inject custom registration workflow
    factory.UserService = new Registration<IUserService>(resolver => AuthObjects.AuthUserService);

    var scopeStore = new InMemoryScopeStore(Scopes.Get());
    factory.ScopeStore = new Registration<IScopeStore>(scopeStore);
    var clientStore = new InMemoryClientStore(Clients.Get());
    factory.ClientStore = new Registration<IClientStore>(clientStore);

    var cors = new InMemoryCorsPolicyService(Clients.Get());
    factory.CorsPolicyService = new Registration<ICorsPolicyService>(cors);

    ...

    var options = new IdentityServerOptions
    {
        SiteName = "Authentication",
        SigningCertificate = LoadCertificate(),
        Factory = factory,
        AuthenticationOptions = authOptions
    };

    ...
});

我注意到IdentityServer3日志条目中写着“CORS request made for path: /connect/authorize”,而不是“CORS request made for path: /auth/connect/authorize”。但是查看IdentityServer3源代码表明,这可能不是问题所在。
也许是InMemoryCorsPolicyService没有被选中?
有任何想法可以解决AJAX调用的ApiController无法工作的问题吗?
使用NuGet安装了Thinktecture.IdevtityServer3 v1.6.2。
更新:
我正在与IdentityServer3开发人员进行交流,但仍然无法解决问题。如果有帮助的话:

https://github.com/IdentityServer/IdentityServer3/issues/1697


app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); - GH DevOps
嘿 @Gavin,你有找到让这个工作的方法吗? - Luis Lavieri
很遗憾,@LuisLavieri,我在这个相关项目上已经没有时间了。 - Gavin
这是关于Identity Server 4的,但它可能会有所帮助:https://dev59.com/5cz6oIgBc1ULPQZF2q-0#74506370?noredirect=1#comment131522477_74506370 - MD Zand
4个回答

1

CORS 真是个噩梦! 这是一个浏览器的问题,这就是为什么你在 IE 和 Chrome 中看到不同的行为。

服务器上配置 CORS 至少有两种方式。当客户端使用 Origin 标头发出请求时,您必须告诉服务器是否接受它--如果接受,则服务器会将 Access-Control-Allow-Origin 标头添加到浏览器的响应中。

在 MVC / webAPI 中,您必须添加 CORS 服务,设置 CORS 策略,然后像这样使用 .UseCors

builder.Services.AddCors((options =>
            {
                if (settings.AllowedCorsOrigins.Length > 0)
                {
                    options.AddDefaultPolicy(builder => 
                    { 
                        builder.SetIsOriginAllowedToAllowWildcardSubdomains();
                        builder.AllowAnyHeader().AllowAnyMethod().WithOrigins(settings.AllowedCorsOrigins); 
                    });
                }
                if (isDevelopment)
                {
                    options.AddPolicy("localhost", builder => 
                    {
                        builder.SetIsOriginAllowedToAllowWildcardSubdomains();
                        builder.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed((string origin) => { return origin.Contains("localhost"); }); });
                    }
            });

并且

            app.UseCors();
            if (app.Environment.IsDevelopment())
            {
                app.UseCors("localhost");
            }


通常,您希望将允许主机列表作为字符串数组放在您的appsettings.json中。并注意SetIsOriginAllowedToAllowWildcardSubdomains可能会出现的问题。
此外,IdentityServer有自己的附加CORS设置,这些设置“除外”于标准的MVC / webAPI设置。它们在ClientCorsOrigin表中,并且不支持通配符子域。您可以通过实现自己的ICorsPolicyService来避开整个障碍,以使用与您的appsettings.json相同的设置,类似如下:
    public class CorsPolicyService : ICorsPolicyService
    {
        private readonly CorsOptions _options;

        public CorsPolicyService(IOptions<CorsOptions> options)
        {
            _options = options.Value;
        }

        private bool CheckHost(string host)
        {
            foreach (string p in _options.AllowedCorsOrigins)
            {
                if (Regex.IsMatch(host, Regex.Escape(p).Replace("\\*", "[a-zA-Z0-9]+"))) // Hyphen?
                {
                    return true;
                }
            }
            return false;
        }

        public Task<bool> IsOriginAllowedAsync(string origin)
        {
            return Task.FromResult(CheckHost(origin));
        }
    }


0

你尝试过添加 https 的 URL 吗?- client.AllowedCorsOrigins.Add("https://test.myapp.com");


回到2015年,https并不是那么强制性的。 - Gavin
是的,但请检查配置的URL和错误消息,看看是否存在不匹配。在开发过程中,有时我也会遇到同样的问题,当我忘记进行配置时就会出现这种情况。 - Santosh Karanam

0

0

要允许跨域策略,请将以下代码添加到您的 Startup.cs 文件中。

代码

services.AddCors(options =>
{
options.AddDefaultPolicy(
                  builder =>
                  {
                      builder.WithOrigins("https://localhost:44343") //replace with your localhost 
                        .AllowAnyHeader()
                        .AllowAnyMethod();
                  });
                  });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接