You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Docker中配置带有OpenIddict的.NET Core 9 Web API的证书问题咨询

在Docker中配置带有OpenIddict的.NET Core 9 Web API的证书问题咨询

我正在把一个集成了OpenIddict的ASP.NET Core 9 Web API容器化并部署到Docker中。按照OpenIddict的推荐,我生成了两个独立于HTTPS证书的RSA自签名证书:一个用于签名,一个用于加密,这些证书是我本地用.NET Core的CertificateRequest API生成的。

现在我在部署过程中遇到了证书加载相关的问题(比如生产环境下证书找不到、权限不足无法读取等),下面是我的相关代码和配置文件,想请教大家对应的解决方案:

Program.cs 中的OpenIddict配置部分

builder.Services.AddOpenIddict()
    .AddCore(opt => {
        opt.UseEntityFrameworkCore()
           .UseDbContext<ApplicationDbContext>();
    })
    .AddServer(opt => {
        opt.SetTokenEndpointUris("connect/token");
        opt.AllowClientCredentialsFlow().AllowRefreshTokenFlow();
        opt.AllowPasswordFlow().AllowRefreshTokenFlow();
        opt.AcceptAnonymousClients();

        if (builder.Environment.IsProduction())
        {
            try
            {
                var signingCertPath = config["OpenIddict:Certificates:Signing:Path"];
                var signingCertPassword = config["OpenIddict:Certificates:Signing:Password"];
                var encryptionCertPath = config["OpenIddict:Certificates:Encryption:Path"];
                var encryptionCertPassword = config["OpenIddict:Certificates:Encryption:Password"];

                bool certificatesLoaded = false;

                if (!string.IsNullOrWhiteSpace(signingCertPath))
                {
                    if (File.Exists(signingCertPath))
                    {
                        Log.Information("Loading signing certificate from: {Path}", signingCertPath);
                        opt.AddSigningCertificate(new X509Certificate2(signingCertPath, signingCertPassword));
                        certificatesLoaded = true;
                    }
                    else
                    {
                        Log.Warning("Signing certificate file not found: {Path}", signingCertPath);
                    }
                }

                if (!string.IsNullOrWhiteSpace(encryptionCertPath))
                {
                    if (File.Exists(encryptionCertPath))
                    {
                        Log.Information("Loading encryption certificate from: {Path}", encryptionCertPath);
                        opt.AddEncryptionCertificate(new X509Certificate2(encryptionCertPath, encryptionCertPassword));
                    }
                    else
                    {
                        Log.Warning("Encryption certificate file not found: {Path}", encryptionCertPath);
                    }
                }

                if (!certificatesLoaded && OperatingSystem.IsWindows())
                {
                    var signingThumbprint = config["OpenIddict:Certificates:Signing:Thumbprint"];
                    var signingStoreLocation = config["OpenIddict:Certificates:Signing:StoreLocation"];

                    if (!string.IsNullOrWhiteSpace(signingThumbprint))
                    {
                        Log.Information("Loading signing certificate from Windows Certificate Store: {Thumbprint}", signingThumbprint);
                        opt.AddSigningCertificate(CertificateHelper.GetCertificateByThumbprint(signingThumbprint, signingStoreLocation!));
                        certificatesLoaded = true;
                    }
                }

                if (!certificatesLoaded)
                {
                    Log.Warning("No production certificates found, falling back to development certificates");
                    opt.AddDevelopmentEncryptionCertificate()
                       .AddDevelopmentSigningCertificate();
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to load production certificates, falling back to development certificates");
                opt.AddDevelopmentEncryptionCertificate()
                   .AddDevelopmentSigningCertificate();
            }
        }
        else
        {
            // Development certificates for local development
            opt.AddDevelopmentEncryptionCertificate()
               .AddDevelopmentSigningCertificate();
        }

        opt.DisableAccessTokenEncryption();
        opt.UseAspNetCore()
           .EnableTokenEndpointPassthrough()
           .EnableAuthorizationEndpointPassthrough();

        if (builder.Environment.IsDevelopment())
        {
            opt.UseAspNetCore().DisableTransportSecurityRequirement();
        }
    });

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:9.0-bookworm-slim AS base
USER root
RUN mkdir -p /app/logs && \
    mkdir -p /app/certificates && \
    chmod 755 /app/logs && \
    chmod 700 /app/certificates

# Create app user if it doesn't exist and set ownership
RUN groupadd -r app && useradd -r -g app app || true
RUN chown -R app:app /app

WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["Rock.Identity.API.csproj", "."]
RUN dotnet restore "./Rock.Identity.API.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./Rock.Identity.API.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Rock.Identity.API.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
COPY appsettings*.json ./ 2>/dev/null || echo "No additional appsettings files found"
COPY certificates/*.pfx /app/certificates/ 2>/dev/null || echo "No certificates found in build context - using development certificates"

RUN if [ -d "/app/certificates" ] && [ "$(ls -A /app/certificates 2>/dev/null)" ]; then \
    chown -R app:app /app/certificates && \
    chmod 600 /app/certificates/*.pfx 2>/dev/null || true; \
fi

USER $APP_UID
ENTRYPOINT ["dotnet", "Rock.Identity.API.dll"]

docker-compose.yml(片段)

version: '3.8'
services:
  identity-api:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3400:8080"

具体问题

  1. 我的Dockerfile中关于证书的复制和权限配置是否存在问题?
  2. 在Linux容器环境下,加载本地生成的PFX证书需要注意哪些权限或路径细节?
  3. 有没有更优雅的方式在Docker中管理OpenIddict的签名/加密证书,避免路径或权限相关的陷阱?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:19:35