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

如何在同一IIS站点仅对特定ASP.NET Core API要求mTLS并允许本地无证书调用

解决方案:IIS进程内托管ASP.NET Core实现路由+来源差异化mTLS要求

核心思路

由于TLS握手发生在IIS解析路由之前,无法通过web.config的<location>元素针对路由强制mTLS。因此采用全局协商证书+应用层逻辑控制的方案:

  1. IIS全局配置为请求但不强制客户端证书;
  2. ASP.NET Core中间件根据路由和请求来源,决定是否验证证书。

步骤1:修改IIS站点级SSL配置

在web.config的根<system.webServer>节点下设置全局SSL参数,让IIS在握手时请求客户端证书(可选):

<system.webServer>
  <security>
    <access sslFlags="Ssl, SslNegotiateCert" />
  </security>
  <!-- 其他已有配置(如aspNetCore节点)保留不变 -->
</system.webServer>
  • Ssl:强制HTTPS访问;
  • SslNegotiateCert:握手时请求客户端证书,但不强制提供。

步骤2:添加ASP.NET Core中间件控制证书验证

在Program.cs中添加自定义中间件,放在路由匹配逻辑之前(确保先拦截API路由请求):

using System.Net;

var builder = WebApplication.CreateBuilder(args);

// 保留原有服务配置(如MVC、认证等)
builder.Services.AddControllersWithViews();

var app = builder.Build();

// 自定义mTLS控制中间件
app.Use(async (context, next) =>
{
    // 仅针对/api开头的路由执行检查
    if (context.Request.Path.StartsWithSegments("/api"))
    {
        bool isLocalRequest = false;
        if (context.Connection.RemoteIpAddress != null)
        {
            // 判断是否为本地请求:回环地址或服务器自身IP
            isLocalRequest = context.Connection.LocalIpAddress != null 
                ? context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress) 
                : IPAddress.IsLoopback(context.Connection.RemoteIpAddress);
        }

        // 非本地请求必须提供有效客户端证书
        if (!isLocalRequest)
        {
            var clientCert = context.Connection.ClientCertificate;
            if (clientCert == null || !clientCert.Verify())
            {
                context.Response.StatusCode = StatusCodes.Status403Forbidden;
                await context.Response.WriteAsync("访问API需提供有效客户端证书");
                return;
            }

            // 可选:添加自定义证书校验逻辑(如检查颁发者、主题等)
            // if (!clientCert.Issuer.Equals("预期证书颁发者")) { ... }
        }
    }

    // 非API路由或本地API请求,直接执行后续逻辑
    await next();
});

// 保留原有中间件配置
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

关键说明

  1. TLS握手限制:现代TLS协议不支持连接中途重新协商证书,因此必须在全局层面让IIS请求证书,再由应用层决定是否强制验证;
  2. 本地请求覆盖:通过IP地址判断,覆盖服务器内部进程发起的localhost、127.0.0.1及服务器自身IP调用场景;
  3. 证书有效性校验:clientCert.Verify()自动验证证书的链信任、过期时间等,可根据业务需求替换为自定义校验规则;
  4. 非API路由兼容:所有非/api开头的路由直接跳过证书检查,完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:23:14