- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我希望能够针对 Identity Server 进行身份验证(STS)来自 docker 机器的外部和内部。
我无法设置适用于容器内外的正确权限。如果我将权限设置为内部名称 mcoidentityserver:5000
则 API 可以进行身份验证,但客户端无法获取 token ,因为客户端位于 docker 网络之外。如果我将权限设置为外部名称 localhost:5000
那么客户端可以获得 token 但 API 无法识别权限名称(因为在这种情况下 localhost
是主机)。
我应该将权限设置为什么?或者我可能需要调整 docker 网络?
我正在设置使用 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
?是的,Client 和 API 都可以调用相同的 URL hostname:5000
如果:
hostname:5000
(检查防火墙、网络拓扑等)DNS 是最棘手的部分。如果您有任何问题,我建议您尝试通过其公开的 IP 访问 Identity Server,而不是解析 hostname
。
关于docker - 如何在 docker 机器内外使用 IdentityServer4?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43911536/
我是一名优秀的程序员,十分优秀!