你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

用于验证请求和响应的 API 管理策略

本文提供 API 管理策略的参考,这些策略根据 API 定义中定义的架构或者补充性 JSON 或 XML 架构验证 REST 或 SOAP API 请求和响应。 验证策略可防范标头或有效负载注入或敏感数据泄漏等漏洞。 详细了解常见 API 漏洞

虽然验证策略不能取代 Web 应用程序防火墙,但它们可让用户灵活应对依赖于静态预定义规则的安全产品所不能涵盖的其他威胁种类。

有关策略的详细信息:

验证策略

  • 验证内容 - 根据一个或多个 API 架构验证请求或响应正文的大小或内容。 支持的架构格式为 JSON 和 XML。
  • 验证参数 - 根据 API 架构验证请求头、查询或路径参数。
  • 验证标头 - 根据 API 架构验证响应标头。
  • 验证状态代码 - 根据 API 架构验证响应中的 HTTP 状态代码。

注意

验证策略可使用的 API 架构的最大大小为 4 MB。 如果架构超过此限制,验证策略将在运行时返回错误。 若要提高限制,请与支持部门联系。

操作

每个验证策略包含一个用于指定操作的特性,该操作将由 API 管理在根据 API 架构验证 API 请求或响应中的实体时执行。

  • 可为 API 架构中表示的元素指定操作,并可以根据策略为 API 架构中未表示的元素指定操作。

  • 在策略的子元素中指定的操作将替代针对其父级指定的操作。

可用操作:

操作 说明
ignore 跳过验证。
prevent 阻止请求或响应处理,记录详细的验证错误,并返回错误。 检测到第一组错误时便中断处理。
detect 记录验证错误,但不中断请求或响应处理。

日志

有关在执行策略期间出现的验证错误的详细信息将记录到策略根元素的 errors-variable-name 特性中指定的 context.Variables 内的变量。 在 prevent 操作中进行配置后,验证错误会阻止进一步的请求或响应处理,并会传播到 context.LastError 属性。

若要调查错误,请使用跟踪策略将上下文变量中的错误记录到 Application Insights

性能影响

添加验证策略可能会影响 API 吞吐量。 以下一般原则适用:

  • API 架构越大,吞吐量越低。
  • 请求或响应中的有效负载越大,吞吐量越低。
  • 相比于有效负载大小,API 架构大小对性能的影响更大。
  • 在某些情况下,根据若干 MB 大小的 API 架构进行验证可能会导致请求或响应超时。 在“消耗”和“开发人员”服务层级中,这种影响更为明显。

我们建议在预期的生产工作负载中执行负载测试,以评估验证策略对 API 吞吐量的影响。

验证内容

validate-content 策略根据一个或多个支持的架构验证请求或响应正文的大小或内容。

注意

按照策略声明中提供的顺序设置策略的元素和子元素。 为了帮助你配置此策略,门户提供了基于窗体的引导式编辑器。 详细了解如何设置或编辑 API 管理策略

下表显示了策略支持的架构格式和请求或响应内容类型。 内容类型值不区分大小写。

格式 内容类型
JSON 示例:application/json
application/hal+json
XML 示例:application/xml
SOAP 允许的值:application/soap+xml(适用于 SOAP 1.2 API)
text/xml(适用于 SOAP 1.1 API)

验证的内容

该策略针对架构在请求或响应中验证以下内容:

  • 存在所有必需的属性。
  • 如果架构设置了 additionalProperties 字段,就存在或不存在其他属性。 可以用 allow-additional-properties 属性替代。
  • 所有属性的类型。 例如,如果架构将属性指定为整数,则请求(或响应)必须包含整数,而不是另一种类型,如字符串。
  • 属性的格式(如在架构中指定)—例如,正则表达式(如果指定了关键字 pattern),整数为 minimum 等。

提示

有关可用于架构的正则表达式模式约束的示例,请参阅 OWASP 验证正则表达式存储库

策略语句

<validate-content unspecified-content-type-action="ignore|prevent|detect" max-size="size in bytes" size-exceeded-action="ignore|prevent|detect" errors-variable-name="variable name">
    <content-type-map any-content-type-value="content type string" missing-content-type-value="content type string">
        <type from|when="content type string" to="content type string" />
    </content-type-map>
    <content type="content type string" validate-as="json|xml|soap" schema-id="schema id" schema-ref="#/local/reference/path" action="ignore|prevent|detect" allow-additional-properties="true|false" />
</validate-content>

示例

JSON 架构验证

在以下示例中,API 管理将内容类型标头为空的请求或内容类型标头为 application/hal+json 的请求解释为内容类型为 application/json 的请求。 然后,API 管理在检测模式下针对一个为 API 定义中的 application/json 内容类型定义的架构执行验证。 将阻止有效负载大于 100 KB 的消息。 即使将架构的 additionalProperties 字段配置为支持其他属性,包含其他属性的请求也会被阻止。

<validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestBodyValidation">
    <content-type-map missing-content-type-value="application/json">
        <type from="application/hal+json" to="application/json" />
    </content-type-map>
    <content type="application/json" validate-as="json" action="detect" allow-additional-properties="false" />
</validate-content>

SOAP 架构验证

在以下示例中,API 管理将任何请求都解释为内容类型为 application/soap+xml(SOAP 1.2 API 使用的内容类型)的请求,而不考虑传入内容类型。 请求在到达时可能带有空的内容类型标头、内容类型标头 text/xml(由 SOAP 1.1 API 使用)或其他内容类型标头。 然后,API 管理从 SOAP 信封中提取 XML 有效负载,并针对名为“myschema”的架构在预防模式下执行验证。 将阻止有效负载大于 100 KB 的消息。

<validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestBodyValidation">
    <content-type-map any-content-type-value="application/soap+xml" />
    <content type="application/soap+xml" validate-as="soap" schema-id="myschema" action="prevent" /> 
</validate-content>

元素

名称 说明 必须
validate-content 根元素。
content-type-map 添加此元素,将传入请求或响应的内容类型映射到用于触发验证的另一个内容类型。
content 添加其中的一个或多个元素可以验证请求或响应中的内容类型或映射的内容类型,并执行指定的操作。

属性

名称 说明 必须 默认
unspecified-content-type-action 针对其内容类型未在 API 架构中指定的请求或响应执行的操作 空值
max_size 请求或响应正文的最大长度(以字节为单位),根据 Content-Length 标头进行检查。 如果请求正文或响应正文经过压缩,则此值是解压缩后的长度。 最大允许值:102,400 字节 (100 KB)。 (如果需要增加此限制,请联系支持。) 空值
size-exceeded-action 针对其正文超过 max-size 中指定大小的请求或响应执行的操作 空值
errors-variable-name context.Variables 中的要将验证错误记录到的变量的名称。 空值
any-content-type-value 用于验证请求或响应正文的内容类型,与传入内容类型无关。 空值
missing-content-type-value 当传入内容类型缺失或为空时用于验证请求或响应正文的内容类型。 空值
content-type-map \ type 添加一个或多个此类元素,以将传入内容类型映射到用于验证请求或响应正文的内容类型。 使用 from 指定已知的传入内容类型,或将 when 与策略表达式配合使用以指定与条件匹配的任何传入内容类型。 如果已指定此项,则会替代 any-content-type-valuemissing-content-type-value 中的映射。 空值
content \ type 要为其执行正文验证的内容类型,在已指定此项的情况下针对 content-type-mapping 中映射的内容类型标头或值进行检查。 如果为空,此值将应用到 API 架构中指定的每个内容类型。

若要验证 SOAP 请求和响应(validate-as 特性设置为“soap”),请将 type 设置为 application/soap+xml(适用于 SOAP 1.2 API)或 text/xml(适用于 SOAP 1.1 API)。
空值
validate-as 用于验证具有匹配 type 的请求或响应正文的验证引擎。 支持的值:“json”、“xml”、“soap”。

指定“soap”时,请求或响应中的 XML 将从 SOAP 信封中提取出来,并根据 XML 架构进行验证。
空值
schema-id 添加到 API 管理实例以进行内容验证的现有架构的名称。 如果未指定此项,则使用 API 定义中的默认架构。 空值
schema-ref 对于 schema-id 中指定的 JSON 架构,可选择引用 JSON 文档中的有效本地引用路径。 示例:#/components/schemas/address。 此特性应返回 API 管理将其作为有效 JSON 架构进行处理的 JSON 对象。

就 XML 架构来说,schema-ref 不受支持,任何顶级架构元素都可用作 XML 请求或响应有效负载的根。 此验证会检查从 XML 请求或响应有效负载根开始的所有元素是否都遵循所提供的 XML 架构。
空值
action 要对其正文与指定内容类型不匹配的请求或响应执行的操作 空值
allow-additional-properties 布尔值。 对于 JSON 架构,指定是否实现架构中配置的 additionalProperties 值的运行时替代:
- true:支持请求或响应正文中的其他属性,即使将 JSON 架构的 additionalProperties 字段配置为不支持其他属性。
- false:不支持请求或响应正文中的其他属性,即使将 JSON 架构的 additionalProperties 字段配置为支持其他属性。

如果未指定属性,策略会根据架构中 additionalProperties 字段的配置验证其他属性。
空值

内容验证架构

默认情况下,对请求或响应内容的验证使用 API 定义中的 JSON 或 XML 架构。 可以手动指定这些架构,也可以在将 API 从 OpenAPI 或 WSDL 规范导入 API 管理时自动生成这些架构。

使用 validate-content 策略,你可以根据需要针对已添加到 API 管理实例并且不属于 API 定义的一个或多个 JSON 或 XML 架构进行验证。 添加到 API 管理的架构可在多个 API 中重复使用。

若要使用 Azure 门户将架构添加到 API 管理实例,请执行以下操作:

  1. 门户中导航到 API 管理实例。

  2. 在左侧菜单的“API”部分,选择“架构”>“+ 添加”。

  3. 在“创建架构”窗口中,执行以下操作:

    1. 为架构输入一个“名称”(ID)。
    2. 在“架构类型”中,选择“JSON”或“XML”。
    3. 输入“说明”。
    4. 在“创建方法”中执行以下操作之一:
      • 选择“新建”,然后输入或粘贴架构。
      • 选择“从文件导入”或“从 URL 导入”,然后输入架构位置。

        备注

        若要从 URL 导入某个架构,需要能够在浏览器中通过 Internet 访问该架构。

    5. 选择“保存”。

    创建架构

API 管理在相对 URI /schemas/<schemaId> 处添加架构资源,架构将显示在“架构”页面的列表中。 选择要在架构编辑器中查看其属性或进行编辑的架构。

备注

一个架构可以交叉引用添加到 API 管理实例的其他架构。 例如,使用类似于以下内容的元素包括添加到 API 管理的 XML 架构:

<xs:include schemaLocation="/schemas/myschema" />

提示

GitHub 上提供用于解析 WSDL 和 XSD 架构引用以及将生成的架构成批导入到 API 管理的开源工具。

使用情况

此策略可在以下策略范围中使用。

  • 策略节: 入站、出站、错误时

  • 策略范围: 所有范围

验证参数

validate-parameters 策略根据 API 架构验证请求中的头、查询或路径参数。

重要

如果使用低于 2021-01-01-preview 的管理 API 版本导入了某个 API,validate-parameters 策略可能不起作用。 可能需要使用管理 API 版本 2021-01-01-preview 或更高版本重新导入你的 API

注意

按照策略声明中提供的顺序设置策略的元素和子元素。 为了帮助你配置此策略,门户提供了基于窗体的引导式编辑器。 详细了解如何设置或编辑 API 管理策略

策略语句

<validate-parameters specified-parameter-action="ignore|prevent|detect" unspecified-parameter-action="ignore|prevent|detect" errors-variable-name="variable name"> 
    <headers specified-parameter-action="ignore|prevent|detect" unspecified-parameter-action="ignore|prevent|detect">
        <parameter name="parameter name" action="ignore|prevent|detect" />
    </headers>
    <query specified-parameter-action="ignore|prevent|detect" unspecified-parameter-action="ignore|prevent|detect">
        <parameter name="parameter name" action="ignore|prevent|detect" />
    </query>
    <path specified-parameter-action="ignore|prevent|detect">
        <parameter name="parameter name" action="ignore|prevent|detect" />
    </path>
</validate-parameters>

示例

在此示例中,将以防护模式验证所有查询和路径参数,以检测模式验证头。 替代多个头参数的验证:

<validate-parameters specified-parameter-action="prevent" unspecified-parameter-action="prevent" errors-variable-name="requestParametersValidation"> 
    <headers specified-parameter-action="detect" unspecified-parameter-action="detect">
        <parameter name="Authorization" action="prevent" />
        <parameter name="User-Agent" action="ignore" />
        <parameter name="Host" action="ignore" />
        <parameter name="Referrer" action="ignore" />
    </headers>   
</validate-parameters>

元素

名称 说明 必须
validate-parameters 根元素。 针对请求中的所有参数指定默认验证操作。
headers 添加此元素可以替代针对请求中的头参数执行的默认验证操作。
query 添加此元素可以替代针对请求中的查询参数执行的默认验证操作。
path 添加此元素可以替代针对请求中的 URL 路径参数执行的默认验证操作。
parameter 为命名参数添加一个或多个元素可以替代验证操作的更高级别的配置。

属性

名称 说明 必须 默认
specified-parameter-action 针对 API 架构中指定的请求参数执行的操作

headersquerypath 元素中提供时,该值将替代 specified-parameter-action 元素中的 validate-parameters 值。
空值
unspecified-parameter-action 要针对未在 API 架构中指定的请求参数执行的操作

headersquery 元素中提供时,该值将替代 validate-parameters 元素中的 unspecified-parameter-action 值。
空值
errors-variable-name context.Variables 中的要将验证错误记录到的变量的名称。 空值
name 要替代其验证操作的参数的名称。 此值不区分大小写。 空值
action 针对具有匹配名称的参数执行的操作。 如果该参数已在 API 架构中指定,此值将替代更高级别的 specified-parameter-action 配置。 如果该参数未在 API 架构中指定,此值将替代更高级别的 unspecified-parameter-action 配置。 空值

使用情况

此策略可在以下策略范围中使用。

  • 策略节: 入站

  • 策略范围: 所有范围

验证头

validate-headers 策略根据 API 架构验证响应头。

重要

如果使用低于 2021-01-01-preview 的管理 API 版本导入了某个 API,validate-headers 策略可能不起作用。 可能需要使用管理 API 版本 2021-01-01-preview 或更高版本重新导入该 API。

注意

按照策略声明中提供的顺序设置策略的元素和子元素。 为了帮助你配置此策略,门户提供了基于窗体的引导式编辑器。 详细了解如何设置或编辑 API 管理策略

策略语句

<validate-headers specified-header-action="ignore|prevent|detect" unspecified-header-action="ignore|prevent|detect" errors-variable-name="variable name">
    <header name="header name" action="ignore|prevent|detect" />
</validate-headers>

示例

<validate-headers specified-header-action="ignore" unspecified-header-action="prevent" errors-variable-name="responseHeadersValidation" />

元素

名称 说明 必须
validate-headers 根元素。 针对响应中的所有头指定默认验证操作。
header 为命名的头添加一个或多个元素可以替代针对响应中的头执行的默认验证操作。

属性

名称 说明 必须 默认
specified-header-action 针对 API 架构中指定的响应头执行的操作 空值
unspecified-header-action 要针对未在 API 架构中指定的响应头执行的操作 空值
errors-variable-name context.Variables 中的要将验证错误记录到的变量的名称。 空值
name 要替代其验证操作的头的名称。 此值不区分大小写。 空值
action 针对具有匹配名称的头执行的操作。 如果该头已在 API 架构中指定,此值将替代 specified-header-action 元素中的 validate-headers 值。 否则,它将替代 validate-headers 元素中的 unspecified-header-action 值。 空值

使用情况

此策略可在以下策略范围中使用。

  • 策略节: outbound、on-error

  • 策略范围: 所有范围

验证状态代码

validate-status-code 策略根据 API 架构验证响应中的 HTTP 状态代码。 此策略可用于防止泄漏后端错误(可能包含堆栈跟踪)。

注意

按照策略声明中提供的顺序设置策略的元素和子元素。 为了帮助你配置此策略,门户提供了基于窗体的引导式编辑器。 详细了解如何设置或编辑 API 管理策略

策略语句

<validate-status-code unspecified-status-code-action="ignore|prevent|detect" errors-variable-name="variable name">
    <status-code code="HTTP status code number" action="ignore|prevent|detect" />
</validate-status-code>

示例

<validate-status-code unspecified-status-code-action="prevent" errors-variable-name="responseStatusCodeValidation" />

元素

名称 说明 必须
validate-status-code 根元素。
status-code 为 HTTP 状态代码添加一个或多个元素可以替代针对响应中的状态代码执行的默认验证操作。

属性

名称 说明 必须 默认
unspecified-status-code-action 要针对未在 API 架构中指定的响应中的 HTTP 状态代码执行的操作 空值
errors-variable-name context.Variables 中的要将验证错误记录到的变量的名称。 空值
code 要替代其验证操作的 HTTP 状态代码。 空值
action 要针对未在 API 架构中指定的匹配状态代码执行的操作。 如果该状态代码已在 API 架构中指定,此替代将不会生效。 空值

使用情况

此策略可在以下策略范围中使用。

  • 策略节: outbound、on-error

  • 策略范围: 所有范围

验证错误

API 管理生成以下格式的验证错误:

{
 "Name": string,
 "Type": string,
 "ValidationRule": string,
 "Details": string,
 "Action": string
}

下表列出了验证策略的所有可能错误。

  • 详细信息:可用于调查错误。 不应公开共享。
  • 公共响应:返回到客户端的错误。 不会泄漏实现详细信息。

当验证策略指定 prevent 操作并产生错误时,API 管理的响应将包括 HTTP 状态代码:在入站部分中应用该策略时为 400,在出站部分应用该策略时为 502。

名称 类型 验证规则 详细信息 公共响应 操作
validate-content
RequestBody SizeLimit 请求正文的长度为 {size} 个字节,超过了配置的限制({maxSize} 字节)。 请求正文的长度为 {size} 个字节,超过了限制({maxSize} 字节)。 detect / prevent
ResponseBody SizeLimit 响应正文的长度为 {size} 个字节,超过了配置的限制({maxSize} 字节)。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{messageContentType} RequestBody 未指定 不允许未指定的内容类型 {messageContentType}。 不允许未指定的内容类型 {messageContentType}。 detect / prevent
{messageContentType} ResponseBody 未指定 不允许未指定的内容类型 {messageContentType}。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
ApiSchema API 的架构不存在或无法解析。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
ApiSchema API 的架构未指定定义。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{messageContentType} RequestBody / ResponseBody MissingDefinition API 的架构不包含与内容类型 {messageContentType} 关联的定义 {definitionName}。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{messageContentType} RequestBody IncorrectMessage 请求正文不符合与内容类型 {messageContentType} 关联的定义 {definitionName}。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
请求正文不符合与内容类型 {messageContentType} 关联的定义 {definitionName}。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
detect / prevent
{messageContentType} ResponseBody IncorrectMessage 响应正文不符合与内容类型 {messageContentType} 关联的定义 {definitionName}。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
RequestBody ValidationException 无法验证 {messageContentType} 内容类型的请求正文。

{exception details}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
ResponseBody ValidationException 无法验证 {messageContentType} 内容类型的响应正文。

{exception details}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
validate-parameters / validate-headers
{paramName} / {headerName} QueryParameter / PathParameter / RequestHeader 未指定 不允许未指定的 {path parameter / query parameter / header} {paramName}。 不允许未指定的 {path parameter / query parameter / header} {paramName}。 detect / prevent
{headerName} ResponseHeader 未指定 不允许未指定的头 {headerName}。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
ApiSchema API 的架构不存在或无法解析。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
ApiSchema API 架构未指定定义。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{paramName} QueryParameter / PathParameter / RequestHeader / ResponseHeader MissingDefinition API 的架构不包含与 {query parameter / path parameter / header} {paramName} 关联的定义 {definitionName}。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{paramName} QueryParameter / PathParameter / RequestHeader IncorrectMessage 请求不能包含 {query parameter / path parameter / header} {paramName} 的多个值。 请求不能包含 {query parameter / path parameter / header} {paramName} 的多个值。 detect / prevent
{headerName} ResponseHeader IncorrectMessage 响应不能包含头 {headerName} 的多个值。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{paramName} QueryParameter / PathParameter / RequestHeader IncorrectMessage {query parameter / path parameter / header} {paramName} 的值不符合定义。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
{query parameter / path parameter / header} {paramName} 的值不符合定义。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
detect / prevent
{headerName} ResponseHeader IncorrectMessage 头 {headerName} 的值不符合定义。

{valError.Message} 行: {valError.LineNumber},位置: {valError.LinePosition}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{paramName} QueryParameter / PathParameter / RequestHeader IncorrectMessage 无法根据定义分析 {query parameter / path parameter / header} {paramName} 的值。

{ex.Message}
无法根据定义分析 {query parameter / path parameter / header} {paramName} 的值。

{ex.Message}
detect / prevent
{headerName} ResponseHeader IncorrectMessage 无法根据定义分析头 {headerName} 的值。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{paramName} QueryParameter / PathParameter / RequestHeader ValidationError 无法验证 {Query parameter / Path parameter / Header} {paramName}。

{exception details}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
{headerName} ResponseHeader ValidationError 无法验证头 {headerName}。

{exception details}
由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent
validate-status-code
{status-code} StatusCode 未指定 不允许响应状态代码 {status-code}。 由于发生内部错误,无法处理请求。 请与 API 所有者联系。 detect / prevent

下表列出了验证错误的所有可能原因值以及可能的消息值:

原因 消息
错误的请求 针对上下文变量的 {Details},针对客户端的 {Public response}
不允许响应 针对上下文变量的 {Details},针对客户端的 {Public response}

后续步骤

有关使用策略的详细信息,请参阅: