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

借助应用网关互认证服务变量实现APIM客户端证书验证

APIM通过Application Gateway传递的证书变量实现客户端证书验证方案

核心前提

你的APIM部署在VNet内部模式,前端Application Gateway(AGW)完成了客户端证书互认证,证书无法直接传递到APIM,因此无法直接使用APIM内置的context.Request.Certificate.Verify()或<validate-client-certificate>策略。但可以通过AGW的互认证服务变量转发证书相关信息到APIM,再在APIM策略中完成验证。


第一步:AGW端配置(转发证书相关信息)

  1. 确保AGW已启用客户端证书互认证。
  2. 在AGW的请求头重写规则中,添加自定义请求头,将AGW的互认证服务变量映射到这些头中传递给APIM:
    • 示例映射:
      • X-Client-Cert -> client_certificate(Base64编码的完整证书内容)
      • X-Cert-Issuer -> client_certificate_issuer(证书颁发者DN)
      • X-Cert-Subject -> client_certificate_subject(证书主题DN)
      • X-Cert-Expiry -> client_certificate_expiry(证书过期时间,UTC格式字符串)

第二步:APIM端验证实现

由于无法直接赋值context.Request.Certificate对象,提供两种验证方案:

方案一:直接验证转发的证书字段(简单高效)

直接通过AGW转发的自定义头完成四项验证,无需重建证书对象:

<policies>
    <inbound>
        <base />
        <!-- 检查证书是否存在 -->
        <choose>
            <when condition="@(!context.Request.Headers.ContainsKey("X-Client-Cert"))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>未提供客户端证书</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 验证证书过期时间 -->
        <choose>
            <when condition="@(DateTime.Parse(context.Request.Headers.GetValueOrDefault("X-Cert-Expiry", "")) < DateTime.UtcNow)">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>客户端证书已过期</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 验证指定颁发者 -->
        <choose>
            <when condition="@(!context.Request.Headers.GetValueOrDefault("X-Cert-Issuer", "").Equals("CN=你的指定颁发者", StringComparison.OrdinalIgnoreCase))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>无效的证书颁发者</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 验证指定主题 -->
        <choose>
            <when condition="@(!context.Request.Headers.GetValueOrDefault("X-Cert-Subject", "").Equals("CN=你的指定主题", StringComparison.OrdinalIgnoreCase))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>无效的证书主题</set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

方案二:重建证书对象进行验证(支持复杂场景)

如果需要使用X509Certificate2的原生方法(如Verify()),可以通过AGW转发的Base64证书内容重建证书对象:

<policies>
    <inbound>
        <base />
        <!-- 检查证书是否存在 -->
        <choose>
            <when condition="@(!context.Request.Headers.ContainsKey("X-Client-Cert"))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>未提供客户端证书</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 从Base64内容重建证书对象 -->
        <set-variable name="clientCert" value="@(new System.Security.Cryptography.X509Certificates.X509Certificate2(Convert.FromBase64String(context.Request.Headers.GetValueOrDefault("X-Client-Cert", ""))))" />
        
        <!-- 验证证书有效性(含过期检查) -->
        <choose>
            <when condition="@(!((System.Security.Cryptography.X509Certificates.X509Certificate2)context.Variables["clientCert"]).Verify())">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>无效的客户端证书</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 验证指定颁发者 -->
        <choose>
            <when condition="@(!((System.Security.Cryptography.X509Certificates.X509Certificate2)context.Variables["clientCert"]).Issuer.Equals("CN=你的指定颁发者", StringComparison.OrdinalIgnoreCase))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>无效的证书颁发者</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 验证指定主题 -->
        <choose>
            <when condition="@(!((System.Security.Cryptography.X509Certificates.X509Certificate2)context.Variables["clientCert"]).Subject.Equals("CN=你的指定主题", StringComparison.OrdinalIgnoreCase))">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>无效的证书主题</set-body>
                </return-response>
            </when>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

关于证书吊销状态验证

AGW默认不启用证书吊销检查,需要手动开启:

  1. 进入AGW的SSL设置,找到“客户端证书验证”部分。
  2. 开启“验证客户端证书吊销状态”,选择CRL或OCSP验证方式。
  3. 开启后,AGW会自动拦截已吊销的证书,不会转发请求到APIM,因此APIM无需额外处理吊销验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 18:57:03