使用微信小程序调用APIM(API Management)中的接口,发现POST和PUT请求被拦截,返回的状态码为200,可是无消息内容。jquery
在小程序中的调用JS代码如:小程序
经过浏览器测试获得的响应体为:微信小程序
如上图所见,微信小程序中发出的POST请求Status Code为200 OK,但Response Length为0。因为在模拟器(Chrome浏览器模拟)并无如正常的CORS域名同样报错消息,因此没法明确知道是什么状况致使这一问题。api
附:正常的CORS报错信息为:跨域
Access to XMLHttpRequest at 'https://test01.azure-api.cn/echo/resource1111' from origin 'https://localhost:44356' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.浏览器 |
jquery.js:10099 POST https://test01.azure-api.cn/echo/resource1111 net::ERR_FAILED缓存 |
在碰见此类不明确问题时,须要找出问题点。因此这次问题的排查方向以下:安全
1) 在APIM的门户中,使用Test功能测试接口(APIM门户提供测试接口的功能)服务器
2) 使用Postman工具,发送API请求进行测试微信
3) 在一样的代码中访问另外一个API或者另外一个APIM中的接口
经过测试,发现针对同一接口,第一,二的测试都是能够成功访问。在第三个测试中,发现其余APIM的接口能够经过微信小程序正常访问。经过以上步骤能够肯定,是APIM的某些策略的设定影响了请求处理。因此在检查在APIM的配置策略中,发现对API配置了CORS策略。并且经过删除策略进行验证(注:删除策略后,可能须要等待45分钟左右才会生效),POST,PUT请求从微信小程序中访问成功。
在进一步分析APIM的CORS策略,有一个terminate-unmatched-request属性,它的目的就是终止不匹配CORS设定的请求,默认值为True,它会返回一个空的200请求。
Name |
Description |
Required |
Default |
terminate-unmatched-request |
此属性控制与CORS策略设置不匹配的跨域请求的处理。
当将OPTIONS请求做为pre-flight请求(预请求)处理且与CORS策略设置不匹配时:
当GET或HEAD请求包含Origin报头(并所以做为跨域请求处理)且与CORS策略设置不匹配时:
Source: https://docs.microsoft.com/en-us/azure/api-management/api-management-cross-domain-policies#CORS |
No |
true |
经过根本缘由的分析,发现APIM中配置的策略为:
<policies> <inbound> <base /> <cors allow-credentials="true"> <allowed-origins> <origin>http://localhost:9372</origin> </allowed-origins> <allowed-methods preflight-result-max-age="300"> <method>GET</method> <method>POST</method> <method>PUT</method> <method>OPTIONS</method> <method>PATCH</method> <method>DELETE</method> </allowed-methods> <allowed-headers> <header>x-zumo-installation-id</header> <header>x-zumo-application</header> <header>x-zumo-version</header> <header>x-zumo-auth</header> <header>Authorization</header> <header>content-type</header> <header>accept</header> </allowed-headers> <expose-headers> <header>x-zumo-installation-id</header> <header>x-zumo-application</header> </expose-headers> </cors> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>
返回空200请求的消息体Origin值截图:
以上Allowed Origins中,只有 https://localhost:9372 容许跨域访问,而在微信小程序的POST的测试请求中,Request所携带的Origin值为 http://127.0.0.1:27323 端口,因此该POST请求没法配置CORS策略,返回200的空响应。当在CORS策略中添加 http://127.0.0.1:27323或者设置 * 后,请求成功。
API Management cross domain policies:https://docs.microsoft.com/en-us/azure/api-management/api-management-cross-domain-policies#CORS
CORS
cors
策略向操做或 API 添加跨源资源共享 (CORS) 支持,以便从基于浏览器的客户端执行跨域调用。CORS 容许浏览器与服务器交互,并肯定是否容许特定的跨源请求(例如,经过某个网页上的 JavaScript 对其余域执行 XMLHttpRequests 调用)。 与只容许同源请求相比,它的灵活性更高,并且比容许全部跨源请求更安全。
策略语句
<cors allow-credentials="false|true"> <allowed-origins> <origin>origin uri</origin> </allowed-origins> <allowed-methods preflight-result-max-age="number of seconds"> <method>http verb</method> </allowed-methods> <allowed-headers> <header>header name</header> </allowed-headers> <expose-headers> <header>header name</header> </expose-headers> </cors>示例
此示例演示如何支持预检请求,例如那些具备自定义标头或 GET 和 POST 以外的方法的预检请求。 若要支持自定义标头和其余 HTTP 谓词,请使用
allowed-methods
和allowed-headers
部分,如如下示例所示。<cors allow-credentials="true"> <allowed-origins> <!-- Localhost useful for development --> <origin>http://localhost:8080/</origin> <origin>http://example.com/</origin> </allowed-origins> <allowed-methods preflight-result-max-age="300"> <method>GET</method> <method>POST</method> <method>PATCH</method> <method>DELETE</method> </allowed-methods> <allowed-headers> <!-- Examples below show Azure Mobile Services headers --> <header>x-zumo-installation-id</header> <header>x-zumo-application</header> <header>x-zumo-version</header> <header>x-zumo-auth</header> <header>content-type</header> <header>accept</header> </allowed-headers> <expose-headers> <!-- Examples below show Azure Mobile Services headers --> <header>x-zumo-installation-id</header> <header>x-zumo-application</header> </expose-headers> </cors>
元素
名称 描述 必须 默认 cors 根元素。 是 不适用 allowed-origins 包含的 origin
元素说明了跨域请求的容许来源。allowed-origins
可能包含单个origin
元素,该元素指定容许任何源的*
,或者包含一个或多个内含 URI 的origin
元素。是 不适用 origin 值能够是容许全部源的 *
,或者是用于指定单个源的 URI。 URI 必须包括方案、主机和端口。是 若是 URI 中省略了端口,则端口 80 用于 HTTP,端口 443 用于 HTTPS。 allowed-methods 若是容许 GET 或 POST 以外的方法,则此元素是必需的。 包含 method
元素,用于指定支持的 HTTP 谓词。 值*
指示全部方法。否 若是此部分不存在,则支持 GET 和 POST。 method 指定 HTTP 谓词。 若是 allowed-methods
部分存在,则至少一个method
元素是必需。不适用 allowed-headers 此元素包含 header
元素,用于指定能够包括在请求中的标头的名称。否 不适用 expose-headers 此元素包含 header
元素,用于指定能够经过客户端访问的标头的名称。否 不适用 标头 指定标头名称。 若是节存在,则 allowed-headers
或expose-headers
中至少一个header
元素是必需。不适用 属性
名称 描述 必须 默认 allow-credentials 预检响应中的 Access-Control-Allow-Credentials
标头将设置为此属性的值,会影响客户端在跨域请求中提交凭据的功能。否 false preflight-result-max-age 预检响应中的 Access-Control-Max-Age
标头将设置为此属性的值,会影响用户代理缓存预检响应的功能。否 0 使用状况
- 策略节: 入站
- 策略范围: 全部范围