ASP.NET 核心 Restful Web API Https - 客户端连接证书错误

ASP.NET Core Restful Web API Https - Client Connection Certificate Errors

我构建了一个使用 JWT 进行身份验证的 ASP.NET Core 3.1 Web API;发布项目并部署到 Windows 2019 服务器 运行ning IIS。

我在 IIS 中创建了如下站点:

  1. 创建了新的应用程序池,'No Managed Code' 作为 .NET CLR 版本。通常网站 运行 在 IIS 工作进程中,但在 .NET Core 中它们 运行 作为一个单独的进程,因此应用程序池中不需要 .NET 运行时。

  2. 为我的 ASP.NET 核心应用程序创建了一个新网站:选择之前创建的应用程序池,将物理路径设置为包含已发布应用程序的文件夹,选择 HTTPS 作为绑定并还在 SSL 证书下拉列表中选择证书到我从 Comodo 获得的证书。我还设置了主机名并将 'Require server name indication' 设置为 true - 因为我有旧版 WCF 站点,它们具有不同的主机名但位于同一 IP 上。

在 Postman 中,当我发送启用了 SSL 证书验证的请求时,我收到 SSL 错误:Hostname/IP 与证书的 altnames 不匹配。关闭 SSL 验证后,它可以正常工作。

使用 HttpClient 创建 .NET 桌面客户端并向站点发送请求时出现错误:基础连接已关闭:无法为 SSL/TLS 安全建立信任关系频道.

当我 Google 这个问题时,我发现大部分文章与人们在开发环境中使用自签名证书有关。

如果我将以下代码添加到我的客户端,它可以正常工作:

if (http_client == null)
{
    var handler = new HttpClientHandler()
    {
         AllowAutoRedirect = false,
         ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
         SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
    };
    http_client = new HttpClient(handler);
}

为什么我会收到这些 SSL 错误?我的站点配置不正确吗? 我想尽快向开发人员提供对该站点的访问权限,但我担心他们在连接时会遇到问题。有些将从 iOS 环境连接,其他则来自不同的网站服务器平台。

Startup.cs 网络 API

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors();
    services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.IgnoreNullValues = true);

    // configure strongly typed settings objects
    var appSettingsSection = Configuration.GetSection("AppSettings");
    services.Configure<AppSettings>(appSettingsSection);

    // configure jwt authentication
    var appSettings = appSettingsSection.Get<AppSettings>();
    var key = Encoding.ASCII.GetBytes(appSettings.Secret);
    services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false,
            // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
            ClockSkew = TimeSpan.Zero
        };
    });

    // configure DI for application services
    services.AddScoped<IUserService, UserService>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseRouting();
    app.UseHttpsRedirection();
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        gFunc.SetFolderPaths(true);
    }
    // global cors policy
    app.UseCors(x => x
       .SetIsOriginAllowed(origin => true)
       .AllowAnyMethod()
       .AllowAnyHeader()
       .AllowCredentials());
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(x => x.MapControllers());
}

如我的 OP 中所述,我之前 运行 在 IIS 上只设置了一个站点,该站点提供一些遗留 WCF 服务。然后,我在同一 IP 地址上为 .NET Core Web API 添加了另一个站点。为此,我必须在 IIS 中为新站点启用服务器名称指示 (SNI)。

但是,我发现在使用 SNI 时,您必须为所有网站打开它,而不仅仅是一个。我在服务器上使用 ssllabs.com 到 运行 测试,它返回 证书名称不匹配 ,并返回另一个 domain/hostname 的证书。

运行 服务器上的“netsh http show sslcert”显示了两个证书,但 WCF 站点的证书未链接到主机名 - 仅链接到 IP 地址。因此,任何进入该 IP 地址的请求都只会获得该证书。

为另一个 (WCF) 站点启用 SNI 解决了这个问题。现在每个证书都绑定到 IP/Hostname.