在 azure Web 应用程序容器上部署 .net Core 3 Linux 容器,出现 IdentityServer4 认证/http 错误

2024-05-27

我正在尝试使用.Net Core 干净架构应用程序模板 https://github.com/jasontaylordev/CleanArchitecture并使其在容器中运行并通过 Azure CI/CD 管道进行部署

我在 Linux 容器中本地运行模板的容器化版本,端口为 5001,一切运行良好。

我的天蓝色管道构建过程正常工作,它在我的容器注册表中创建图像。

问题一旦我部署/发布到容器的 Web 应用程序,该应用程序就会失败并抛出以下错误:

应用程序启动异常 System.InvalidOperationException:无法在“CurrentUser\My”上找到主题为“CN=localhost”的有效证书 Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromStoreCert(字符串 主题、字符串 storeName、StoreLocation storeLocation、DateTimeOffset 当前时间)

我做了什么:

  1. 下列的这些文档来自 MS https://learn.microsoft.com/en-us/aspnet/core/security/docker-https?view=aspnetcore-3.1我创建了一个本地开发证书:

    dotnet dev-certs https -ep %USERPROFILE%\.aspnet\https\aspnetapp.pfx -p { password here }

    dotnet dev-certs https --trust

  2. 然后我将其作为私有 .pfx 证书导入到 Web 应用程序中。

  3. 我添加了一个应用程序设置WEBSITE_LOAD_CERTIFICATES与证书的“拇指”值

  4. 我在 Identity Server appSettings.json 部分中使用了导入证书的“主机名”(在我的例子中主机名=localhost)

当 Web 应用程序加载时,它会显示 :( 应用程序错误,并且 docker 日志给出了我上面引用的错误。

我很确定这与身份服务器设置和此处的 appSettings.json 值有关:

  "IdentityServer": {
    "Key": {
      "Type": "Store",
      "StoreName": "My",
      "StoreLocation": "CurrentUser",
      "Name": "CN=localhost"
    }
  }

有人可以帮我弄清楚如何解决这个错误吗?

编辑 1 - 手动指定 IdentityServer 密钥文件

这肯定与身份服务器有关。我尝试手动将证书设置为 appSettings.json 中的文件,如下所示:

  "IdentityServer": {
    "Key": {
      "Type": "File",
      "FilePath": "aspnetapp.pfx",
      "Password": "Your_password123"
    }
  }

现在我得到这个错误:

使用存储标志加载“/app/aspnetapp.pfx”处的证书文件 ”。应用程序启动异常System.InvalidOperationException: 加载证书时出错。文件 找不到“/app/aspnetapp.pfx”。 Microsoft.AspNetCore.ApiAuthorization.IdentityServer.SigningKeysLoader.LoadFromFile

我将其添加到 dockerfile 中:

WORKDIR /app
COPY ["/aspnetapp.pfx", "/app"]
RUN find /app

正如您从下图中看到的,这些文件显示在应用程序的构建目录中:

我还确保 .gitignore 或 .dockerignore 文件不会忽略 aspnetapp.pfx。

我不明白为什么它不会加载这个文件。看起来它就存在于它应该存在的地方。

使用证书拇指和更新的路径进行编辑2

所以我使用了 tnc1977 建议并将其作为我的身份密钥设置

  "IdentityServer": {
    "Key": {
      "Type": "File",
      "FilePath": "/var/ssl/private/<thumb_value>.p12",
      "Password": "Your_password123"
    }
  }

然而,这又产生了另一个错误:

加载证书时出错。密码要么是 不正确或该进程没有存储密钥的权限 密钥集“EphemeralKeySet” 互操作+加密+OpenSslCryptographicException:错误:23076071:PKCS12 例程:PKCS12_parse:mac验证失败

编辑3:有效的Azure应用程序证书

我购买了 Azure 应用程序证书并添加了设置了 TSL 的自定义域,但出现了相同的错误

编辑4:在代码startup.cs中加载证书-新错误:

我现在知道我无法使用证书存储 CurrentUser/My 因为那是针对 Windows 的。 Linux 容器必须在代码中手动加载证书。

我正在使用已添加到 azure Web 应用程序的应用程序证书的指纹。它是一个私有的 Azure 应用程序证书,并且已针对自定义域进行了验证。

我将此代码添加到我的 statup.cs configureservices 中(我知道硬编码这些值不是最佳实践,但我只想看看它是否可以加载证书,我将切换到环境变量和密钥保管库):

        // linux file path for private keys
        var cryptBytes = File.ReadAllBytes("/var/ssl/private/<thumbprint>.p12");
        var cert = new X509Certificate2(cryptBytes, "");

        services.AddIdentityServer().AddSigningCredential(cert);

我输入一个空白密码,因为我认为这是你应该做的。我现在在我的 docker 日志中收到以下错误,这使我相信已加载证书,现在该错误与我使用两者有关services.AddIdentityServer().AddSigningCredential(cert);在启动.cs中配置服务 and 应用程序.UseIdentityServer()在启动.cs中配置:

未处理的异常。 System.InvalidOperationException:装饰器已注册类型:IAuthenticationService。

我不知道如何将证书添加到 app.UseIdentityServer();线。

EDIT 5

经过更多挖掘后,不幸的是@tnc1997 答案将不起作用。 在 asp.net core 3 中调用应用程序.UseIdentityServer in my 启动.cs内部尊重一个方法,该方法将在 appsetting(environment).json 文件中查找身份服务器 Key、File、Pass 等。

因此,即使我在 tnc1997 所示的代码中加载了证书,应用程序仍然会在设置文件中查找。因此设置文件必须包含 IS4 密钥的正确详细信息。

此外,azure 不会将证书放置在 Linux 容器中的典型受信任位置。根据我的阅读,执行此操作的唯一方法似乎是安装一个卷(在本例中为天蓝色存储文件共享)并使用上传到该文件共享的证书。

我可以确认这在本地有效,但现在我在运行容器、前端加载时仍然遇到问题,并且 Web api 项目似乎无法启动。我将发布另一个问题来解决该问题。


原答案

我认为问题可能是您正在尝试使用 Windows 证书存储在 Linux 容器中加载证书。

文档here https://learn.microsoft.com/en-us/azure/app-service/configure-ssl-certificate-in-code#load-certificate-in-linux-apps很好地概述了如何在 Linux 托管应用程序中使用应用程序服务私有证书:

  1. 在 Azure 门户中,从左侧菜单中选择“应用服务”>“”。
  2. 从应用程序的左侧导航中,选择 TLS/SSL 设置,然后选择私钥证书 (.pfx) 或公钥证书 (.cer)。
  3. 找到您要使用的证书并复制指纹。
  4. 要访问应用代码中的证书,请将其指纹添加到 WEBSITE_LOAD_CERTIFICATES 应用设置。
  5. The WEBSITE_LOAD_CERTIFICATES app setting makes the specified certificate accessible to your Linux hosted apps (including custom container apps) as files. The files are found under the following directories:
    • 私有证书 - /var/ssl/private(.p12 文件)
    • 公共证书 - /var/ssl/certs(.der 文件)
  6. 使用下面的代码示例将指定的证书加载到您的 Linux 托管应用程序(包括自定义容器应用程序)中:
    using System;
    using System.IO;
    using System.Security.Cryptography.X509Certificates;
    
    var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
    var cert = new X509Certificate2(bytes);
    

签署凭证

以下是我用来生成签名凭据的步骤:

  1. Install OpenSSL https://www.openssl.org/.
  2. Generate private key and public certificate.
    1. Run openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout example.com.key -out example.com.crt -subj "/CN=example.com" -days 365替换example.com与网站的名称。
  3. Combine the above into a single PFX file.
    1. Run openssl pkcs12 -export -out example.com.pfx -inkey example.com.key -in example.com.crt替换example.com与网站的名称。
  4. Upload the PFX file to Azure.
    1. 在 Azure 门户中,从左侧菜单中选择“应用服务”>“”。
    2. 从应用程序的左侧导航中,选择 TLS/SSL 设置,然后选择私钥证书 (.pfx),然后上传上述 PFX 文件。
  5. Configure app settings.
    1. 将上述 PFX 文件的指纹添加到应用服务中的 WEBSITE_LOAD_CERTIFICATES 应用设置。

身份服务器

下面的代码示例显示了完整的Startup.cs可用于启动并运行 IdentityServer 应用程序的配置:

namespace IdentityServer
{
    public class Startup
    {
        public Startup(IConfiguration configuration, IWebHostEnvironment environment)
        {
            Configuration = configuration;
            Environment = environment;
        }

        public IConfiguration Configuration { get; }

        public IWebHostEnvironment Environment { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            void ConfigureDbContext(DbContextOptionsBuilder builder)
            {
                builder.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"));
            }

            var builder = services.AddIdentityServer()
                .AddConfigurationStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
                .AddOperationalStore(options => { options.ConfigureDbContext = ConfigureDbContext; });

            if (Environment.IsDevelopment())
            {
                builder.AddDeveloperSigningCredential();
            }
            else
            {
                try
                {
                    var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
                    var certificate = new X509Certificate2(bytes);
                    builder.AddSigningCredential(certificate);
                }
                catch (FileNotFoundException)
                {
                    throw new Exception($"The certificate with the thumbprint \"{Configuration["WEBSITE_LOAD_CERTIFICATES"].Substring(0, 8)}...\" could not be found.");
                }
            }
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

            app.UseIdentityServer();
        }
    }
}

干净的架构

下面的代码示例显示了完整的DependencyInjection.cs可用于启动并运行 Clean Architecture 应用程序的配置:

namespace CleanArchitecture.Infrastructure
{
    public static class DependencyInjection
    {
        public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
        {
            void ConfigureDbContext(DbContextOptionsBuilder builder)
            {
                if (configuration.GetValue<bool>("UseInMemoryDatabase"))
                {
                    builder.UseInMemoryDatabase("CleanArchitectureDb");
                }
                else
                {
                    builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
                }
            }

            services.AddDbContext<ApplicationDbContext>(ConfigureDbContext);

            services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

            services.AddScoped<IDomainEventService, DomainEventService>();

            services.AddDefaultIdentity<ApplicationUser>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            var builder = services.AddIdentityServer()
                .AddConfigurationStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
                .AddOperationalStore(options => { options.ConfigureDbContext = ConfigureDbContext; })
                .AddAspNetIdentity<ApplicationUser>();

            var bytes = File.ReadAllBytes($"/var/ssl/private/{Configuration["WEBSITE_LOAD_CERTIFICATES"]}.p12");
            var certificate = new X509Certificate2(bytes);
            builder.AddSigningCredential(certificate);

            services.AddTransient<IDateTime, DateTimeService>();
            services.AddTransient<IIdentityService, IdentityService>();
            services.AddTransient<ICsvFileBuilder, CsvFileBuilder>();

            services.AddAuthentication()
                .AddIdentityServerJwt();

            return services;
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 azure Web 应用程序容器上部署 .net Core 3 Linux 容器,出现 IdentityServer4 认证/http 错误 的相关文章

随机推荐

  • 底部带有缩略图的轮播

    在 Codenameone 应用程序中 我尝试开发一个底部带有缩略图列表的轮播 我使用 Tabs 控件在表单中心以轮播样式显示文件 具有不同类型 如图像 视频 文本 按钮等 并使用另一个 Tabs 控件在底部显示缩略图图像 第一个轮播文件的
  • 如何在 Pro*C 查询中指定变量表达式列表?

    我尝试优化的 Pro C 查询出现问题 解释一下 我们的应用程序在一个巨大的数据库中搜索行 这些行存在于多种语言中 旧代码为数组中的每种语言选择一行 现在 由于这些查询是我们应用程序中最耗时的部分 因此我只想进行一个直接写入数组的查询 语言
  • iOS 的 IAP 收据验证

    我正在开发一个客户端 服务器应用程序 它使用 Apple 的 IAP 和 StoreKit 框架来购买订阅 我们希望客户 iPhone 或 iPad 能够使用 StoreKit 框架通过其 iTunes 帐户向 Apple 进行初始订阅购买
  • 是否可以打开包含类的 .txt/.java 文件,并对其使用反射?

    我的意思是 将其中包含 Java 代码的文件作为类而不是文件打开 所以基本上我想 gt 在自己编写的Java应用程序中打开纯文本文件 txt log java gt 识别文件中的类 例如 public class TestExample p
  • 错误:“raw.githubusercontent.com”的证书不受信任

    我正在尝试使用 wget 通过远程服务器 ssh 从 github 检索一些文件 这是我得到的 wget https raw githubusercontent com aseemk seadragon ajax master seadra
  • 我可以在 NetBeans 中使用或导入 Eclipse 格式化程序吗?

    我们已经使用 Eclipse 很长时间了 我们的每个项目都有格式化程序 现在 我们中的一些人正在转向 NetBeans 是否可以将 Eclipse 格式化程序迁移 同步 导入到 NetBeans 我尝试将 Eclipse 项目导入 NetB
  • 如何在 pandas 中创建求和行和求和列?

    我正在学习可汗学院的统计课程 作为我大学时代的复习 也是让我加快掌握 pandas 和其他科学 Python 的一种方式 我有一张来自可汗学院的表格 看起来像这样 Undergraduate Graduate Total Straight
  • AWS CodeBuild - 如何跳过构建

    我的构建是在每次推送到存储库和每次拉取请求时触发的 因此 CODEBUILD SOURCE VERSION 看起来像 pr 8 或 4570d2e7158cfef687af8da31d1ffec7b02e5ca3 我只希望为 pr 分支执行
  • Android - 材料设计 - NavigationView - 如何放置垂直滚动?

    我正在使用 NavigationViewcompile com android support design 22 2 1 嗯 一切都很好 除非它没有垂直滚动 如何通过xml设置呢 xml
  • 如何使用 maven 或 pom.xml 更新属性文件

    我创建了一个自动化框架 在其中读取属性文件 config properties 中的值 我的 config properties 文件包含以下内容 BrowserName browser Environment env 我正在从属性文件中读
  • JetBrains Rider 可以与 IISExpress 正常工作吗?

    我使用的JetBrains Rider是官网最新版本2019 1 2 免费30天试用 这不是一个损坏的版本 我有一个包含 ASP NET Web API csproj 的解决方案 该解决方案在 IIS 或 VS IISExpress 中正常
  • after_or_equal 验证在 laravel 5.2 中不起作用

    我想比较 start date 和 end date 并且 end date 应等于或大于 start date 我正在使用 after or equal 验证 return Validator make data start date g
  • 如何保留每个单元格中合并单元格的值?

    我创建了一个包含合并单元格的工作表 但合并单元格的值仅存储在第一个单元格中 无论如何 为了在每个单元格中保持相同的值 我使用的公式需要它 谢谢 在 Excel 2003 中 此宏执行以下任务 Public Sub UnmergeAndFil
  • 如何在 symfony 4 注销中重定向到外部网址

    只是想知道 Symfony 4 中是否有一个简单的解决方案 通常用户会注销并返回主页 但是有一个页面会检查用户当前是否在另一个站点上进行了身份验证 如果这是不正确的 我有一个链接可以将用户从我的站点中注销并重定向到外部站点 我在基于 sil
  • 在 .NET 中解析 FIX 协议消息的最有效方法是什么?

    我碰到这个非常相似的问题 https stackoverflow com questions 2311205 the best way to parse a fix message但该问题被标记为 QuickFIX 与我的问题无关 并且大多
  • 如何让Android设备始终处于唤醒模式?

    设备root成功后 现在 我需要使设备始终处于唤醒状态 即始终可见 UI 并且没有黑屏或任何白日梦屏幕 为此 我认为我必须完成以下任务 无锁屏 已关闭 睡眠设置为 从不 白日梦设置为 关闭 我发现都是关于应用程序层的 即有一些应用程序可以完
  • 有什么简单的方法可以完全忽略带有 java url 连接的 ssl ?

    我正在构建一个应用程序 定期检查一些 RSS 提要是否有新内容 其中一些提要只能通过 https 访问 有些具有自签名或以某种方式损坏的证书 我仍然希望能够检查它们 请注意 安全性在此应用程序中不是问题 目标是以最小的努力访问内容 我使用此
  • JavaScript 单选按钮

    我正在尝试制作一些项目 其中我希望在选择专家按钮时显示一个文本框 而在单击学习者按钮时不显示文本框 我已经编写了这段代码 但无法解决问题 请帮忙
  • 为什么我不能将 this 指针显式传递给成员函数?

    c 标准 ISO c 11 中提到第 9 3 1 节 that 可以为其类的对象调用非静态成员函数 类型 或从其类派生的类的对象 第 10 条 类型 使用类成员访问语法 5 2 5 13 3 1 1 尝试使用 g 版本 4 8 2 编译此代
  • 在 azure Web 应用程序容器上部署 .net Core 3 Linux 容器,出现 IdentityServer4 认证/http 错误

    我正在尝试使用 Net Core 干净架构应用程序模板 https github com jasontaylordev CleanArchitecture并使其在容器中运行并通过 Azure CI CD 管道进行部署 我在 Linux 容器