使用一些旧版浏览器在跨域ajax请求中传递自定义标头

时间:2014-03-06 16:52:18

标签: ajax iis http-headers cors

考虑以下跨域请求(在Safari 5.0.2中可复制的f.ex.,任何操作系统):

请求

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://myhost.tld/odata/Account(518059)', false);
xhr.setRequestHeader('Authorization','Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJsb2phYWxpLXdlYmFwaS5jbG91ZGFwcC5uZXQiLCJleHAiOjEzOTQxMjM2MzcsImlzcyI6IldlYkFwaSIsImNhbXBJZCI6MjksInBvcnRhbElkIjozMiwidXNlcklkIjo1MTgwNTl9.c8223aYpb4X7kwYLSmSSQr4wGytxcYtOzTlQuHa9mYU');
xhr.send();
xhr.responseText;

响应

Error: NETWORK_ERR: XMLHttpRequest Exception 101

接头

OPTIONS /odata/Account(518059) HTTP/1.1
Host: myhost.tld
Accept: */*
Accept-Language: en-US
Access-Control-Request-Method: GET
Origin: http://myclient.tld
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.2; en-US) AppleWebKit/533.18.1 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5
Accept-Encoding: gzip, deflate
Access-Control-Request-Headers: Authorization
Content-Length: 0
Connection: keep-alive
Connection: keep-alive

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.5
Access-Control-Allow-Origin: http://myclient.tld
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Authorization
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Thu, 06 Mar 2014 16:37:26 GMT
Content-Length: 0

我验证了web api正确处理了请求并确实使用HTTP 200返回数据。但是,某些旧版浏览器上的请求似乎失败了。因此,我继续对服务器端的授权令牌进行硬编码,并将其从等式中删除:

请求

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://myhost.tld/odata/Account(518059)', false);
xhr.send();
xhr.responseText;

响应

{
    'odata.metadata': 'http://myhost.tld/odata/$metadata#Account/@Element',
    'Id': 518059,
    'userName': '643033849'
}

Voilà,它突然开始工作了。所以,我将整个互联网下载到我的硬盘并阅读它,但无法找到f.ex.的验证。较旧的Safaris不支持带有跨域请求的自定义标头,我也无法在不进入明显的Http Handler或JSONP路由的情况下找到可能的情况。

因此,除了前面提到的“修复”之外,我还能做些什么来安全地将此令牌从我的客户端传输到服务器,从而避免使用自定义标头。或者,有没有办法让它们起作用?

缓存吗

请不要建议这个。除非用户访问了跨域请求的目标站点,否则某些Safari版本(包括5.0.2)会阻止跨域Cookie。

1 个答案:

答案 0 :(得分:0)

最终,我发现没有办法真正解决这个问题。比如,一些旧版本的浏览器根本不支持在CORS请求中传递自定义标头。由于我们在身份验证中使用Json Web Tokens,我真的需要这样做。

因此,我在Application Request Routing (ARR)中找到了这个IIS模块,该模块使用URL Rewrite引擎创建了reverse proxy。更具体地说,将^/odata(.*)$下的所有请求映射到我的后端web api主机。

以下是配置反向代理的高级步骤

  1. 打开IIS管理器
  2. 开放网站
  3. 在功能视图中,选择网址重写(假设已经安装)
  4. 选择添加规则
  5. 在“入站和出站规则”中,选择“反向代理”
  6. 如果您没有安装应用程序请求路由(ARR),它将提示您这样做,接受
  7. 创建规则以将路径映射到后端服务器
  8. 保存后,规则将写入Web.config

    <rewrite>
      <rules>
        <rule name="ODataApiReverseProxy" stopProcessing="true">
          <match url="^odata(.*)$" />
          <action type="Rewrite" url="http://webapi.host.tld/{R:0}" />
        </rule>
      </rules>
      <outboundRules>
        <rule name="ODataRewriteJson" preCondition="ResponseIsJson" patternSyntax="ExactMatch">
          <match filterByTags="None" pattern="webapi.host.tld" />
          <action type="Rewrite" value="client.host.tld" />
        </rule>
        <preConditions>
          <preCondition name="ResponseIsJson">
            <add input="{RESPONSE_CONTENT_TYPE}" pattern="^application/json" />
          </preCondition>
        </preConditions>
      </outboundRules>
    </rewrite>
    

  9. 现在,客户端将完全跳过CORS预检,因为它连接到同一主机。此外,ARR在配置,缓存,负载平衡,监控和管理等方面允许更多。