Azure APIM入站策略获取X-CSRF-Token为空问题求助
Azure APIM入站策略传递X-CSRF-Token为null问题排查
我正在创建Azure API Management(APIM)入站策略,用于将x-csrf-token传递至POST请求,但在追踪中发现该令牌值为null。使用了适用于SAP Gateway的X-CSRF-Token获取策略片段,目前遇到令牌值为null的问题,求排查解决思路。
相关策略代码如下:
<!-- IMPORTANT: - Policy elements can appear only within the <inbound>, <outbound>, <backend> section elements. - To apply a policy to the incoming request (before it is forwarded to the backend service), place a corresponding policy element within the <inbound> section element. - To apply a policy to the outgoing response (before it is sent back to the caller), place a corresponding policy element within the <outbound> section element. - To add a policy, place the cursor at the desired insertion point and select a policy from the sidebar. - To remove a policy, delete the corresponding policy statement from the policy document. - Position the <base> element within a section element to inherit all policies from the corresponding section element in the enclosing scope. - Remove the <base> element to prevent inheriting policies from the corresponding section element in the enclosing scope. - Policies are applied in the order of their appearance, from the top down. - Comments within policy elements are not supported and may disappear. Place your comments between policy elements or at a higher level scope. --> <!-- The policy defined in this file shows how to implement X-CSRF pattern used by many APIs. The example is specific to SAP Gateway. --> <!-- Detailed description of the scenario and solution can be found on: --> <!-- https://github.com/MartinPankraz/AzureSAPODataReader. --> <policies> <inbound> <base /> <authentication-basic username="{{SAP-test-user}}" password="{{SAP-test-PW}}" /> <set-variable name="checkRequestUrl" value="@(context.Request.Url.ToString())" /> <rewrite-uri template="/" /> <choose> <!-- CSRF-token only required for every operation other than GET or HEAD --> <when condition="@(context.Request.Method != "GET" && context.Request.Method != "HEAD")"> <!-- Creating a HEAD subrequest to save request overhead and get the SAP CSRF token and cookie.--> <send-request mode="new" response-variable-name="SAPCSRFToken" timeout="10" ignore-error="false"> <set-url>@(context.Request.Url.ToString())</set-url> <set-method>HEAD</set-method> <set-header name="X-CSRF-Token" exists-action="override"> <value>Fetch</value> </set-header> <set-header name="Authorization" exists-action="override"> <value>@(context.Request.Headers.GetValueOrDefault("Authorization"))</value> </set-header> </send-request> <!-- Extract the token and cookie from the "SAPCSRFToken" and set as header in the POST request. --> <choose> <when condition="@(((IResponse)context.Variables["SAPCSRFToken"]).StatusCode == 200)"> <set-header name="X-CSRF-Token" exists-action="override"> <value>@(((IResponse)context.Variables["SAPCSRFToken"]).Headers.GetValueOrDefault("x-csrf-token"))</value> </set-header> <set-header name="Cookie" exists-action="override"> <value>@{ string rawcookie = ((IResponse)context.Variables["SAPCSRFToken"]).Headers.GetValueOrDefault("Set-Cookie"); string[] cookies = rawcookie.Split(';'); /* new session sends a XSRF cookie */ string xsrftoken = cookies.FirstOrDefault( ss => ss.Contains("sap-XSRF")); /* existing sessions sends a SessionID. No other cases anticipated at this point. Please create a GitHub Pull-Request if you encounter uncovered settings. */ if(xsrftoken == null){ xsrftoken = cookies.FirstOrDefault( ss => ss.Contains("SAP_SESSIONID")); } return xsrftoken.Split(',')[1];}</value> </set-header> </when> </choose> </when> </choose> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
附追踪截图:

排查方向:
- 检查HEAD请求响应状态:策略仅处理响应状态码为200的情况,若SAP Gateway返回401、403等非200状态,令牌提取逻辑不会执行。需在APIM追踪中查看
send-request的实际响应状态码及响应头,确认是否返回了X-CSRF-Token。 - 修正URL重写影响:策略先执行了
<rewrite-uri template="/" />,后续send-request使用的context.Request.Url.ToString()是重写后的URL,可能并非SAP Gateway的有效端点。可将send-request的URL改为之前保存的原始请求URL:@((string)context.Variables["checkRequestUrl"])。 - 验证Authorization头有效性:策略中
send-request的Authorization头取自原始请求,但前面已执行<authentication-basic>,可能原始请求的Authorization头已被覆盖或不存在。可直接使用SAP凭据生成Basic Auth头,或确认context.Request.Headers.GetValueOrDefault("Authorization")能获取有效值。 - 修复Cookie处理逻辑:策略中用
xsrftoken.Split(',')[1]拆分Cookie,若Set-Cookie无逗号会直接报错,导致令牌无法设置。可修改为更稳妥的提取方式:var parts = xsrftoken.Split(','); return parts.Length > 1 ? parts[1].Trim() : parts[0].Trim(); - 核对头名称大小写:SAP Gateway返回的头可能是
X-CSRF-Token而非小写的x-csrf-token,可将提取逻辑改为Headers.GetValueOrDefault("X-CSRF-Token"),确保头名称大小写匹配。
内容的提问来源于stack exchange,提问作者Viknesh
相关产品推荐
相关产品推荐

