docker - 如何在 docker 机器内外使用 IdentityServer4?

标签 docker docker-compose identityserver4

我希望能够针对 Identity Server 进行身份验证(STS)来自 docker 机器的外部和内部。

我无法设置适用于容器内外的正确权限。如果我将权限设置为内部名称 mcoidentityserver:5000 则 API 可以进行身份​​验证,但客户端无法获取 token ,因为客户端位于 docker 网络之外。如果我将权限设置为外部名称 localhost:5000 那么客户端可以获得 token 但 API 无法识别权限名称(因为在这种情况下 localhost 是主机)。

我应该将权限设置为什么?或者我可能需要调整 docker 网络?

图表

红色箭头是我遇到问题的部分。 Three docker containers in a network, a client and PostgreSQL Admin, their ports and a red arrow showing where I think the problem lies.

详情

我正在设置使用 ASP.NET Core API(Linux 上)、Identity Server 4(Linux 上的 ASP.NET Core)和 PostgreSQL 数据库的 Windows 10 docker 开发环境。 PostgreSQL 不是问题,为了完整起见,将其包含在图表中。它映射到 9876,因为我现在还有一个 PostgreSQL 实例在主机上运行。 mco 是我们公司的简称。

我一直在关注Identity Server 4 instructions启动并运行。

代码

我不包括 docker-compose.debug.yml,因为它具有仅与在 Visual Studio 中运行相关的运行命令。

docker-compose.yml

version: '2'

services:
mcodatabase:
    image: mcodatabase
    build:
    context: ./Data
    dockerfile: Dockerfile
    restart: always
    ports:
    - 9876:5432
    environment:
    POSTGRES_USER: mcodevuser
    POSTGRES_PASSWORD: password
    POSTGRES_DB: mcodev
    volumes:
    - postgresdata:/var/lib/postgresql/data
    networks:
    - mconetwork

mcoidentityserver:
    image: mcoidentityserver
    build:
    context: ./Mco.IdentityServer
    dockerfile: Dockerfile
    ports:
    - 5000:5000
    networks:
    - mconetwork

mcoapi:
    image: mcoapi
    build:
    context: ./Mco.Api
    dockerfile: Dockerfile
    ports:
    - 56107:80
    links:
    - mcodatabase
    depends_on:
    - "mcodatabase"
    - "mcoidentityserver"
    networks:
    - mconetwork

volumes:
postgresdata:

networks:
mconetwork:
    driver: bridge

docker-compose.override.yml

这是由 Visual Studio 插件创建的,用于注入(inject)额外的值。

version: '2'

services:
mcoapi:
    environment:
    - ASPNETCORE_ENVIRONMENT=Development
    ports:
    - "80" 

mcoidentityserver:
    environment:
    - ASPNETCORE_ENVIRONMENT=Development
    ports:
    - "5000" 

API Dockerfile

FROM microsoft/aspnetcore:1.1
ARG source
WORKDIR /app
EXPOSE 80
COPY ${source:-obj/Docker/publish} .
ENTRYPOINT ["dotnet", "Mco.Api.dll"]

身份服务器 Dockerfile

FROM microsoft/aspnetcore:1.1
ARG source
WORKDIR /app
COPY ${source:-obj/Docker/publish} .
EXPOSE 5000
ENV ASPNETCORE_URLS http://*:5000
ENTRYPOINT ["dotnet", "Mco.IdentityServer.dll"]

API Startup.cs

我们告诉 API 使用身份服务器并设置权限。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
    {
        // This can't work because we're running in docker and it doesn't understand what localhost:5000 is!
        Authority = "http://localhost:5000", 
        RequireHttpsMetadata = false,

        ApiName = "api1"
    });

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

身份服务器 Startup.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentityServer()
            .AddTemporarySigningCredential()
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryClients(Config.GetClients());
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseIdentityServer();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    }
}

身份服务器配置.cs

public class Config
{
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };
    }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "client",

                // no interactive user, use the clientid/secret for authentication
                AllowedGrantTypes = GrantTypes.ClientCredentials,

                // secret for authentication
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },

                // scopes that client has access to
                AllowedScopes = { "api1" }
            }
        };
    }
}

客户

在控制台应用程序中运行。

var discovery = DiscoveryClient.GetAsync("localhost:5000").Result;
var tokenClient = new TokenClient(discovery.TokenEndpoint, "client", "secret");
var tokenResponse = tokenClient.RequestClientCredentialsAsync("api1").Result;

if (tokenResponse.IsError)
{
    Console.WriteLine(tokenResponse.Error);
    return 1;
}

var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);

var response = client.GetAsync("http://localhost:56107/test").Result;
if (!response.IsSuccessStatusCode)
{
    Console.WriteLine(response.StatusCode);
}
else
{
    var content = response.Content.ReadAsStringAsync().Result;
    Console.WriteLine(JArray.Parse(content));
}

提前致谢。

最佳答案

确保 IssuerUri 设置为显式常量。我们在通过 IP/主机名访问 Identity Server 实例时遇到了类似的问题,并以这种方式解决了它:

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

附:为什么不将权限URL统一为hostname:5000?是的,ClientAPI 都可以调用相同的 URL hostname:5000 如果:

  • 5000端口暴露(我看没问题)
  • DNS 在 docker 容器内解析。
  • 您可以访问 hostname:5000(检查防火墙、网络拓扑等)

DNS 是最棘手的部分。如果您有任何问题,我建议您尝试通过其公开的 IP 访问 Identity Server,而不是解析 hostname

关于docker - 如何在 docker 机器内外使用 IdentityServer4?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43911536/

相关文章:

docker - 使用容器编排处理 EF Core 迁移

Dockerfile 和 docker-compose 不更新新指令

mysql - 云跑: Connecting to Cloud SQL instances

tomcat - 访问docker容器内的Tomcat时出现CORS错误

docker - 使用 Docker Compose 运行时的端口发布

c# - Identity Server 4 - 角色策略不起作用

asp.net-core - 在身份服务器 4 中成功验证后如何在应用程序级别授权用户

asp.net-core - 是否可以将 NoSQL 用于 Identity Server 4?

bash - Docker容器中的Stackdriver Agent

docker - RainLoop + tomav/docker-mailserver:无法从RainLoop Webmail客户端连接到服务器