我正在尝试将我的宠物项目 Docker 化到微服务架构上。我有几个微服务、一个客户端和 duende 身份服务器。在本地,在我的机器上,客户端直接与 duende 服务器通信。当我单击“登录”时,它会将我带到我注册或进行身份验证的身份服务器主机,然后我将返回到带有授权 cookie 的客户端主机。当我对项目进行 dockerize 并指定 localhost 身份服务器进行连接时,出现错误“无法从以下位置获取配置:'https://localhost:44384/.well-known/openid-configuration'。连接被拒绝”。
如果我在浏览器中手动输入此链接:https://localhost:44384/.well-known/openid-configuration,我会得到所需的 json 响应。如果我指定 docker 的内部地址https://app.service.identity,我会收到一条错误消息,指出找不到该页面,因为它会将我带到此链接,该链接仅存在于 docker 内部。我该如何解决这个问题?
docker-compose.yml:
x-app-default-env: &app-default-env
Logging__LogLevel__Default: Information
Logging__LogLevel__Microsoft.AspNetCore: Warning
AllowedHosts: "*"
services:
app:
restart: unless-stopped
image: mango.web
build:
context: ./Mango.Web
volumes:
- ./Mango.Web/wwwroot:/app/wwwroot
environment:
<<: *app-default-env
ServiceUrls__IdentityAPI: https://localhost:44384
ServiceUrls__ProductAPI: http://app.service.product
ServiceUrls__CouponAPI: http://app.service.coupon
ServiceUrls__ShoppingCartAPI: http://app.service.shoppingcart
ServiceUrls__AzureBlobAPI:
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoWEBAPI"
app.service.order:
restart: unless-stopped
image: mango.services.order
build:
context: .
dockerfile: ./Mango.Services.OrderAPI/Dockerfile
environment:
<<: *app-default-env
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoOrderAPI"
ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
CheckoutMessageTopic: "checkoutmessagetopic"
CheckoutSubscription: "mangoOrdersSubscription"
OrderPaymentProcessTopic: "orderpaymentprocesstopic"
OrderPaymentProcessSubscription: "mangoPayment"
OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic"
OrderUpdatePaymentResultSubscription": "mangoOrdersSubscription"
CheckoutMessageQueue: "checkoutqueue"
app.service.azureblobservice:
restart: unless-stopped
image: mango.services.azureblobservice
build: Mango.Services.AzureBlobService
environment:
<<: *app-default-env
ServiceUrls__IdentityServer: http://app.service.identity
ConnectionStrings__BlobStorage: ${CONNECTION_STRINGS_BLOB_STORAGE}
BlobContainerName: ${BLOB_CONTAINER_NAME}
app.service.product:
restart: unless-stopped
image: mango.services.productapi
build: Mango.Services.ProductAPI
environment:
<<: *app-default-env
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoProductAPI"
app.service.payment:
restart: unless-stopped
image: mango.services.payment
build:
context: .
dockerfile: ./Mango.Services.PaymentAPI/Dockerfile
environment:
<<: *app-default-env
ServiceUrls__IdentityServer: http://app.service.identity
ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
OrderPaymentProcessTopic: "orderpaymentprocesstopic"
OrderPaymentProcessSubscription: "mangoPayment"
OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic"
OrderUpdatePaymentResultSubscription: "mangoOrdersSubscription"
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoPaymentAPI"
app.service.shoppingcart:
restart: unless-stopped
image: mango.services.shoppingcart
build:
context: .
dockerfile: ./Mango.Services.ShoppingCartAPI/Dockerfile
environment:
<<: *app-default-env
ServiceUrls__IdentityServer: http://app.service.identity
ServiceUrls__CouponAPI: http://app.service.coupon
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoShoppingCartAPI"
app.service.identity:
restart: unless-stopped
image: mango.services.identity
build: Mango.Services.Identity
volumes:
- ./Mango.Services.Identity/wwwroot:/app/wwwroot
environment:
<<: *app-default-env
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoIdentityAPI"
app.service.email:
restart: unless-stopped
image: mango.services.email
build:
context: .
dockerfile: ./Mango.Services.Email/Dockerfile
environment:
<<: *app-default-env
ConnectionStrings__AzureServiceBus: ${AZURE_SERVICE_BUS_CONNECTION_STRING}
OrderUpdatePaymentResultTopic: "orderupdatepaymentresulttopic"
EmailSubscription: "emailSubscription"
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoEmailAPI"
app.service.coupon:
restart: unless-stopped
image: mango.services.coupon
build: Mango.Services.CouponAPI
environment:
<<: *app-default-env
ServiceUrls__IdentityServer:
ConnectionStrings__DefaultConnection: "Host=db;Port=5432;Username=postgres;Password=postgres;Database=MangoCouponAPI"
docker-compose.override.yml:
services:
app:
ports:
- 8080:80
- 44315:443
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_Kestrel__Certificates__Default__Password=password
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
volumes:
- ~/.aspnet/https:/https:ro
app.service.identity:
ports:
- 44384:443
- 8081:80
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:443;http://+:80
- ASPNETCORE_Kestrel__Certificates__Default__Password=password
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
volumes:
- ~/.aspnet/https:/https:ro
db:
restart: unless-stopped
ports:
- 5433:5432
image: postgres:16
user: root
volumes:
- ../docker/db/data:/var/lib/pgsql/data
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
客户端程序.cs授权:
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
}).AddCookie("Cookies", c => c.ExpireTimeSpan=TimeSpan.FromMinutes(10))
.AddOpenIdConnect("oidc", options =>
{
options.Authority = builder.Configuration["ServiceUrls:IdentityAPI"];
options.GetClaimsFromUserInfoEndpoint = true;
options.ClientId = "mango";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.ClaimActions.MapJsonKey("role", "role", "role");
options.ClaimActions.MapJsonKey("sub", "sub", "sub");
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "role";
options.Scope.Add("mango");
options.SaveTokens = true;
options.RequireHttpsMetadata = false;
options.BackchannelHttpHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
};
});
要诊断和调试客户端和 IdentityServer 之间的通信,可以使用如下代码:
.AddJwtBearer(opt =>
{
opt.BackchannelHttpHandler = new JwtBearerBackChannelListener();
opt.BackchannelTimeout = TimeSpan.FromSeconds(60); //default 60s
...
}
.AddOpenIdConnect(opt =>
{
opt.BackchannelHttpHandler = new JwtBearerBackChannelListener();
opt.BackchannelTimeout = TimeSpan.FromSeconds(60); //default 60s
...
}
然后,示例反向通道侦听器可能如下所示:
namespace Infrastructure
{
/// <summary>
/// Backchannel listener, that will log requests made to our IdentityServer
/// From the IdentityServer in production training class https://www.tn-data.se
/// </summary>
public class BackChannelListener : DelegatingHandler
{
public BackChannelListener() : base(new HttpClientHandler())
{
Console.WriteLine();
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Console.WriteLine("BackChannelListener");
Console.WriteLine("@@@@ SendASync: " + request.RequestUri);
var sw = new Stopwatch();
sw.Start();
var result = base.SendAsync(request, cancellationToken);
result.ContinueWith(t =>
{
sw.Stop();
Console.WriteLine("@@@@ success: " + result.IsFaulted);
Console.WriteLine("@@@@ loadtime: " + sw.ElapsedMilliseconds.ToString());
Console.WriteLine("@@@@ url: " + request.RequestUri);
Serilog.Log.Logger.ForContext("SourceContext", "BackChannelListener")
.ForContext("url", request.RequestUri)
.ForContext("loadtime", sw.ElapsedMilliseconds.ToString() + " ms")
.ForContext("success", result.IsCompletedSuccessfully)
.Information("Loading IdentityServer configuration");
});
return result;
}
}
}
希望这有帮助。