Postman测试API证书认证无证书传入?配置方法与排查
API证书认证配置问题
我是API证书认证(Certificate Authentication)的新手,参考资料编写了API调用时通过TLS握手接受证书的代码。已在Postman的Settings>>Certificates中上传PEM文件,本地测试localhost时断点触发,但未收到传入的证书,请问如何正确配置API的证书认证?
现有代码实现
ServiceCollection扩展类
public static IServiceCollection AddCertificateAuthentication(this IServiceCollection services) { services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme).AddCertificate(options =>{ options.RevocationMode = X509RevocationMode.NoCheck; options.AllowedCertificateTypes = CertificateTypes.All; options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = context =>{ var cert = context.ClientCertificate; if (cert == null) { return Task.FromResult(AuthenticateResult.Fail("No client certificate provided.")); } // 从证书主题中提取通用名称(CN) var cn = cert.Subject.Split(',').FirstOrDefault(part =>part.Trim().StartsWith("CN="))?.Split('=')[1]; if (string.IsNullOrEmpty(cn)) { return Task.FromResult(AuthenticateResult.Fail("Invalid certificate: CN not found.")); } var claims = new[] { new Claim(ClaimTypes.Name, cn), }; var identity = new ClaimsIdentity(claims, CertificateAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, CertificateAuthenticationDefaults.AuthenticationScheme); return Task.FromResult(AuthenticateResult.Success(ticket)); } }; }); services.AddAuthorization(options =>{ options.AddPolicy("RequireCertificate", policy =>{ policy.AddAuthenticationSchemes(CertificateAuthenticationDefaults.AuthenticationScheme); //policy.RequireAuthenticatedUser(); policy.RequireClaim(ClaimTypes.Role); }); }); return services; }
Startup.cs
services.AddCertificateAuthentication();
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{ webBuilder.ConfigureKestrel(options =>{ options.ConfigureHttpsDefaults(httpsOptions =>{ httpsOptions.ClientCertificateMode = ClientCertificateMode.AllowCertificate; }); }); webBuilder.UseStartup<Startup>(); }).UseLoggingFramework(); }
Postman配置截图


问题排查与修复方案
1. 调整Kestrel客户端证书模式
当前ClientCertificateMode.AllowCertificate仅允许客户端提供证书,但不会主动请求证书。需要改为强制要求证书的模式,让Kestrel在TLS握手阶段主动索要客户端证书:
webBuilder.ConfigureKestrel(options =>{ options.ConfigureHttpsDefaults(httpsOptions =>{ // 强制要求客户端提供证书,并验证证书链 httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificate; // 如果不需要验证证书链(仅测试场景),可使用: // httpsOptions.ClientCertificateMode = ClientCertificateMode.RequireCertificateNoValidation; }); });
2. 修正授权策略逻辑
当前授权策略RequireCertificate要求ClaimTypes.Role声明,但证书验证逻辑中仅添加了ClaimTypes.Name,会导致认证通过但授权失败。二选一调整:
- 方式1:移除角色声明要求
services.AddAuthorization(options =>{ options.AddPolicy("RequireCertificate", policy =>{ policy.AddAuthenticationSchemes(CertificateAuthenticationDefaults.AuthenticationScheme); policy.RequireAuthenticatedUser(); // 注释或删除该行 // policy.RequireClaim(ClaimTypes.Role); }); });
- 方式2:在证书验证时添加角色声明
// 在OnCertificateValidated事件中修改claims数组 var claims = new[] { new Claim(ClaimTypes.Name, cn), new Claim(ClaimTypes.Role, "ApiClient") // 添加自定义角色声明 };
3. 验证Postman配置
- 确认上传的PEM文件包含完整的客户端证书(若证书关联私钥,需确保Postman可访问对应私钥文件)
- 确认请求使用HTTPS协议,且证书配置的域名与
localhost匹配(截图中配置无问题) - 检查Postman请求设置,确保未禁用客户端证书发送
4. 优化证书验证事件写法
简化异步逻辑,避免不必要的Task.FromResult包装:
options.Events = new CertificateAuthenticationEvents { OnCertificateValidated = async context =>{ var cert = context.ClientCertificate; if (cert == null) { context.Fail("No client certificate provided."); return; } var cn = cert.Subject.Split(',').FirstOrDefault(part => part.Trim().StartsWith("CN="))?.Split('=')[1]; if (string.IsNullOrEmpty(cn)) { context.Fail("Invalid certificate: CN not found."); return; } var claims = new[] { new Claim(ClaimTypes.Name, cn), new Claim(ClaimTypes.Role, "ApiClient") }; var identity = new ClaimsIdentity(claims, CertificateAuthenticationDefaults.AuthenticationScheme); context.Principal = new ClaimsPrincipal(identity); context.Success(); } };
5. 确保中间件顺序正确
在Startup.cs的Configure方法中按顺序添加认证、授权中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其他中间件(如异常处理、静态文件)... app.UseAuthentication(); app.UseAuthorization(); // 路由、端点等中间件... }
内容的提问来源于stack exchange,提问作者Pathrudu
相关产品推荐
相关产品推荐

