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

.NET Core 5/6 API证书认证经代理时出现403禁止访问问题

解决方案:代理转发下的ASP.NET Core证书认证403问题

问题根源

当请求经过代理转发时,核心问题有两个:

  1. 代理未正确将客户端证书传递至后端应用;
  2. ASP.NET Core默认不信任代理转发的请求头,无法识别真实客户端信息或传递的证书,导致认证失败返回403。

步骤1:配置ASP.NET Core信任代理

在ConfigureServices中添加转发头配置,让应用信任代理的转发信息:

public void ConfigureServices(IServiceCollection services)
{
    // 配置转发头,信任指定代理
    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
        // 将你的代理服务器IP加入信任列表,防止伪造转发头
        options.KnownProxies.Add(IPAddress.Parse("你的代理IP"));
    });

    // 原有的证书认证配置
    services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
        .AddCertificate()
        .AddCertificateCache();

    // 其他服务配置
}

在Configure中,必须将UseForwardedHeaders()放在UseAuthentication()之前:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseForwardedHeaders(); // 这行需前置,确保认证逻辑能获取正确的客户端信息
    app.UseAuthentication();

    // 其他应用中间件配置
}

步骤2:确保代理服务器正确传递客户端证书

根据代理类型调整配置:

  • Nginx:开启请求头传递,并将客户端证书转为Base64通过自定义头转发:
    location / {
        proxy_pass http://你的后端应用地址;
        proxy_pass_request_headers on;
        # 转发客户端证书至后端
        proxy_set_header X-Client-Certificate $ssl_client_cert;
    }
    
  • IIS:在代理站点的SSL设置中开启「要求SSL」和「协商客户端证书」,同时确保后端应用池拥有读取客户端证书的权限。

步骤3:调整证书认证逻辑适配代理场景

如果代理通过请求头传递证书信息(如上述的X-Client-Certificate),修改认证配置从请求头读取并验证证书:

services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.AllowedCertificateTypes = CertificateTypes.All;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                // 从代理传递的请求头获取证书
                var certHeader = context.Request.Headers["X-Client-Certificate"].FirstOrDefault();
                if (!string.IsNullOrEmpty(certHeader))
                {
                    // 清理证书格式(移除首尾标识)
                    var cleanCert = certHeader.Replace("-----BEGIN CERTIFICATE-----", "")
                                             .Replace("-----END CERTIFICATE-----", "")
                                             .Trim();
                    var certBytes = Convert.FromBase64String(cleanCert);
                    var clientCert = new X509Certificate2(certBytes);
                    
                    // 自定义验证逻辑(示例:使用证书主题作为身份标识)
                    context.Principal = new ClaimsPrincipal(
                        new ClaimsIdentity(
                            new[] { new Claim(ClaimTypes.Name, clientCert.Subject) },
                            CertificateAuthenticationDefaults.AuthenticationScheme
                        )
                    );
                    context.Success();
                }
                return Task.CompletedTask;
            }
        };
    })
    .AddCertificateCache();

步骤4:排查验证

添加临时中间件打印请求信息,确认证书和转发头是否正确传递:

app.Use(async (context, next) =>
{
    var clientCert = context.Connection.ClientCertificate;
    var forwardedFor = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
    var certHeader = context.Request.Headers["X-Client-Certificate"].FirstOrDefault();
    
    // 输出至日志或控制台用于排查
    Console.WriteLine($"客户端证书主题: {clientCert?.Subject ?? "未获取到证书"}");
    Console.WriteLine($"转发客户端IP: {forwardedFor ?? "未获取到转发IP"}");
    Console.WriteLine($"代理传递的证书头: {certHeader ?? "未传递证书头"}");
    
    await next();
});

内容的提问来源于stack exchange,提问作者NoviceDeveloper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:50:27