身份服务器 4 和 docker

Identity Server 4 and docker

我正在尝试使用 docker 配置 IdentityServer4,但我无法使其工作。首先,我采用了身份服务器文档的客户端凭证示例:Protecting an API using Client Credentials

IdentityServer
托管在端口 5000

WebApi
托管在端口 5001

在我的 WebApi Startup.cs 文件的 Configure 方法中,我做了以下操作(问题可能出在这里):

 app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://web:5000",                
            RequireHttpsMetadata = false,
            ApiName = "api1"
        });

客户端
而客户

 // Everything is fine here...
 var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
 var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
 var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api");

 // This does not work
 var client = new HttpClient();
 client.SetBearerToken(tokenResponse.AccessToken);
 var response = await client.GetAsync("http://localhost:5001/identity");

问题可能出在我的 WebApi:

1) 如果我将权限设置为 localhost:5000,我会得到一个内部服务器错误:"Unable to obtain configuration from: 'http://localhost:5000/.well-known/openid-configuration'" 这是有道理的,因为 localhost:5000 在这个容器

中是未知的

2) 如果我将权限设置为 http://web:5000 I get an authorization error: "Issuer validation failed. Issuer: 'http://localhost:5000'. Did not match: validationParameters.ValidIssuer: 'http://web:5000' 或 validationParameters.ValidIssuers" 这也有道理,但我不知道是否可以更改权限名称?我也尝试设置IdentityServer 项目中的 IssuerUri 但没有帮助

网络

假设您有两台物理机器:C1 和 C2。每台机器都是一个docker主机。

C1 运行 Auth 容器。

C2 运行 WebApi 容器。

当您在 Auth docker 文件中公开端口 5000 时,地址 C1:5000 应该可以从 WebApi 容器本身的 C2 访问。您可能更喜欢 IP 而不是 DNS,这无关紧要。此外,您应该能够向 http://C1:5000/.well-known/openid-configuration 发出成功的 GET 请求以确保。

要实现这一点,您可能会遇到很多网络问题。例如:

颁发者验证

Issuer validation failed

您的客户端权限 URL 与 Auth 主机名不同。默认情况下,权限 URL 应等于 issuer 属性 值(此 属性 在 Identity Server 自动发现文档响应中)。

issuer 属性 值取决于您客户的网络请求:

GET http://127.0.0.1:6000/.well-known/openid-configuration -> "issuer": "http://127.0.0.1:6000"
GET http://localhost:6000/.well-known/openid-configuration -> "issuer": "localhost:6000"

尝试将 IssuerUri 设置为开发环境的常量:

services.AddIdentityServer(x =>
{
    x.IssuerUri = "foo";
})

实现恒定的issuer值。这允许通过任何有效的 URL(使用 IP、机器名称或 DNS)调用身份服务器:

GET http://anything/.well-known/openid-configuration -> "issuer": "foo"

DiscoveryClient 也验证 issuer 值。这是一个简单的等式 comparison:

public bool ValidateIssuerName(string issuer, string authority)
{
    return string.Equals(issuer, authority, StringComparison.Ordinal);
}

您可以通过以下方式禁用它:

DiscoveryClient.Policy.ValidateIssuerName = false;

仅供参考,生产环境的IssuerUri设置is not recommended

IssuerUri Set the issuer name that will appear in the discovery document and the issued JWT tokens. It is recommended to not set this property, which infers the issuer name from the host name that is used by the clients.