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

使用Azure APIM调用需OAuth2验证的后端API的策略配置求助

Azure APIM 调用OAuth2受保护后端API策略配置方案

原有策略核心问题

  • 令牌提取逻辑错误:原有代码拆分Authorization头后取索引0,获取的是Bearer标识而非实际令牌内容,应取拆分后的索引1内容,同时需补充空值校验避免无认证头的请求抛出异常
  • 令牌请求方法错误:OAuth2标准令牌端点仅接受POST请求,原有配置使用GET方法会导致服务端无法识别请求体中的认证参数
  • 缺少错误处理逻辑:开启请求忽略错误后未校验令牌接口返回状态,直接读取返回报文中的access_token字段,令牌请求失败时会触发空引用异常
  • 无令牌缓存机制:每次用户请求都重复调用令牌接口,会增加链路耗时,同时容易触发令牌接口的频率限制

修正后完整策略

<policies>
    <inbound>
        <base />
        <!-- 提取原始请求中的用户令牌,补充空值校验 -->
        <set-variable name="originBearer" value="@(context.Request.Headers.GetValueOrDefault("Authorization", "").Split(' ').Length >= 2 ? context.Request.Headers.GetValueOrDefault("Authorization", "").Split(' ')[1] : "")" />
        <!-- 优先从缓存读取后端接口令牌 -->
        <cache-lookup-value key="backend-oauth2-token" variable-name="cachedAccessToken" />
        <choose>
            <!-- 缓存无有效令牌时发起令牌请求 -->
            <when condition="@(!context.Variables.ContainsKey("cachedAccessToken"))">
                <send-request ignore-error="false" timeout="20" response-variable-name="bearerTokenResponse" mode="new">
                    <set-url>{{lookupAccessTokenUrl}}</set-url>
                    <!-- 修正为OAuth2标准要求的POST方法 -->
                    <set-method>POST</set-method>
                    <set-header name="Content-Type" exists-action="override">
                        <value>application/x-www-form-urlencoded</value>
                    </set-header>
                    <set-body>@{
                        return $"client_id={{HLR-app-client-id}}&scope={{HLR-scope}}&client_secret={{HLR-secret}}&grant_type=urn:ietf:params:oauth:grant-type:client_credentials&assertion={(string)context.Variables["originBearer"]}&requested_token_use=on_behalf_of";
                    }</set-body>
                </send-request>
                <!-- 校验令牌请求结果 -->
                <choose>
                    <when condition="@(((IResponse)context.Variables["bearerTokenResponse"]).StatusCode == 200)">
                        <set-variable name="requestResponseToken" value="@((string)((IResponse)context.Variables["bearerTokenResponse"]).Body.As<JObject>()["access_token"])" />
                        <!-- 令牌写入缓存,缓存时长设置为比令牌有效期短1分钟,避免使用过期令牌 -->
                        <cache-store-value key="backend-oauth2-token" value="@((string)context.Variables["requestResponseToken"])" duration="3540" />
                    </when>
                    <otherwise>
                        <!-- 令牌获取失败直接返回错误信息 -->
                        <return-response>
                            <set-status code="500" reason="Backend token acquisition failed" />
                            <set-body>@(((IResponse)context.Variables["bearerTokenResponse"]).Body.As<string>())</set-body>
                        </return-response>
                    </otherwise>
                </choose>
            </when>
            <otherwise>
                <!-- 缓存存在令牌直接复用 -->
                <set-variable name="requestResponseToken" value="@((string)context.Variables["cachedAccessToken"])" />
            </otherwise>
        </choose>
        <!-- 替换请求头为后端所需的认证令牌 -->
        <set-header name="Authorization" exists-action="override">
            <value>@($"Bearer {(string)context.Variables["requestResponseToken"]}")</value>
        </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

配置注意事项

  • 如果你使用的是纯客户端凭证流而非On-Behalf-Of流,直接删除请求体中的assertion和requested_token_use参数即可
  • 缓存时长duration可根据你的令牌实际有效期调整,需保证比令牌有效期短至少30秒
  • 所有{{}}包裹的命名值需提前在APIM的「命名值」模块配置完成,敏感参数(如client_secret)建议设置为密钥类型加密存储
  • 确认你的APIM实例已开启内置缓存,若使用的是消费层级APIM,缓存功能不可用时可删除缓存相关策略,每次请求实时获取令牌即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:15:03