gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 12:39:29 25 4
gpt4 key购买 nike

我希望能够针对 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com