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

Azure API Management单API根据所属产品适配AAD令牌或订阅密钥的可行性及实现方案咨询

在Azure API Management中实现单API多产品的混合身份验证

你提到的这个需求确实是APIM里的一个常见痛点——默认情况下,API级别的「需要订阅」设置会直接覆盖产品层面的配置,没法直接让同一个API根据所属产品自动切换身份验证方式。你想到的两个方案都是可行的,我再针对你问的「检查context.Subscription.Key并与产品订阅匹配」的问题,详细说说自定义策略的实现方式:

方案一:双API分产品(简单直观)

这个思路很直接:创建两个指向同一后端服务的API,一个开启「需要订阅」并关联到用订阅密钥验证的产品,另一个关闭「需要订阅」并关联到用AAD令牌验证的产品。

优点:

  • 配置简单,不需要写复杂策略,新手也能快速上手
  • 每个API的验证逻辑独立,排查问题更方便

缺点:

  • 需要维护两个API的配置,后端变更时要同步更新两个API的设置

方案二:自定义策略(单API多验证)

如果想只用一个API实现需求,可以通过APIM的自定义入站策略来实现动态验证逻辑,核心思路是:根据当前请求关联的产品,选择对应的验证方式,同时可以校验订阅密钥是否属于当前产品。

完整策略示例

<policies>
    <inbound>
        <base />
        <!-- 捕获当前请求关联的产品名称 -->
        <set-variable name="targetProduct" value="@(context.Product?.Name)" />
        
        <!-- 分支处理不同产品的验证逻辑 -->
        <choose>
            <!-- 产品A:使用AAD令牌验证 -->
            <when condition="@(context.Variables.GetValueOrDefault<string>("targetProduct") == "ProductA")">
                <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Invalid or expired token.">
                    <openid-config url="https://login.microsoftonline.com/你的租户ID/v2.0/.well-known/openid-configuration" />
                    <required-claims>
                        <claim name="aud" match="any">
                            <value>你的API受众ID</value>
                        </claim>
                    </required-claims>
                </validate-jwt>
            </when>
            <!-- 产品B:使用订阅密钥验证,同时校验密钥所属产品 -->
            <when condition="@(context.Variables.GetValueOrDefault<string>("targetProduct") == "ProductB")">
                <!-- 第一步:验证订阅密钥是否有效 -->
                <validate-credentials header-name="Ocp-Apim-Subscription-Key" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Invalid subscription key.">
                    <required-claims />
                </validate-credentials>
                <!-- 第二步:校验密钥所属产品是否与当前访问产品匹配 -->
                <choose>
                    <when condition="@(context.Subscription?.Product.Name != context.Variables.GetValueOrDefault<string>("targetProduct"))">
                        <return-response>
                            <set-status code="403" reason="Forbidden" />
                            <set-body>{"message": "订阅密钥不属于当前访问的产品"}</set-body>
                        </return-response>
                    </when>
                </choose>
            </when>
            <!-- 未匹配到指定产品的情况 -->
            <otherwise>
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>{"message": "仅允许通过指定产品访问此API"}</set-body>
                </return-response>
            </otherwise>
        </choose>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

关键逻辑说明

  1. 获取当前产品:通过context.Product?.Name可以拿到用户当前访问的产品名称(用户需要通过产品专属的网关URL访问,比如https://你的APIM实例.azure-api.net/ProductA/你的API路径)
  2. AAD令牌验证:用validate-jwt策略校验请求头中的Authorization令牌,确保令牌有效且符合你的租户和API受众要求
  3. 订阅密钥验证与产品匹配:先用validate-credentials验证密钥有效性,再通过context.Subscription?.Product.Name拿到该密钥所属的产品,和当前访问的产品对比,不匹配则返回403

注意事项

  • 必须在API级别取消勾选「需要订阅」,否则APIM会先执行默认的订阅验证,覆盖我们的自定义策略
  • 要确保API已经正确关联到对应的产品(ProductA和ProductB)

方案选择建议

  • 如果你的产品数量少、API配置简单,优先选方案一,维护成本更低
  • 如果需要统一管理API配置、产品数量较多,选方案二更高效,但需要熟悉APIM策略的编写和调试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 12:07:30