如何使用Credentials,HTTP Authorization(CORS)创建XMLHttpRequest跨域?

时间:2014-02-18 10:12:10

标签: http xmlhttprequest cors

我无法使用Authorization标头创建跨域请求(使用Firefox测试)。我有没有身份验证的请求,但是一旦我将withCredentials设置为true,我就无法再从服务器读取响应了。

在服务器上,我发回这些标题(在Flask中使用after_request方法):

resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers['Access-Control-Allow-Credentials'] = 'true'
resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
resp.headers['Access-Control-Allow-Headers'] = 'Authorization'

Firefox实际上没有OPTIONS调用。在客户端,我进行XMLHttpRequest调用:

var xhr = new XMLHttpRequest()
xhr.open( 'POST', 'http://test.local:8002/test/upload', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
    console.log( xhr.status, xhr.statusText )
}
xhr.send(fd)

如果未设置withCredentials,则日志语句会将预期信息记录到控制台。一旦我设置了值,但xhr不允许访问,我只写一个0值和一个空字符串。我没有在这里设置授权标题,但这不会影响我读取结果的能力。

如果我尝试在“打开”命令中添加用户名/密码,我会收到NS_ERROR_DOM_BAD_URI: Access to restricted URI denied错误。

我做错了什么?

2 个答案:

答案 0 :(得分:40)

written an article有一个完整的CORS设置。

我发现了几个可能导致此问题的问题:

  1. 如果正在使用凭据,则Access-Control-Allow-Origin不能是通配符。最简单的方法是将请求的Origin标头复制到此字段。完全不清楚标准为什么不允许使用通配符。
  2. 即使您清除缓存(可能是会话),Firefox也会缓存Access-Control结果。重新启动强制它执行新的OPTIONS请求。为了帮助调试,我添加了标题Access-Control-Max-Age: 1
  3. open命令的用户名/密码显然不可用作凭据。您必须自己添加Authorization标题。 xhr.setRequestHeader( 'Authorization', 'Basic ' + btoa( user + ':' + pass ) )
  4. 总的来说,withCredentials系统相当于脑死亡。简单地编写一个接受授权的服务器作为请求主体的一部分会更容易。

答案 1 :(得分:0)

我发现适用于preflight请求的唯一方法是:

  • 通过将自动化逻辑转换为代码(例如从Apache到PHP)来禁用OPTIONS方法记录的自动化。
  • 将jQuery ajaxwithCredentials一起使用:
$.ajax({
    type: 'POST',
    xhrFields: {
        withCredentials: true
    },
    ...
});

令人惊讶的是,如果我仅将xhr.withCredentials设置为true,它将无法正常工作:

$.ajax({
    type: 'POST',
    beforeSend: function (jqxhr) {
        jqxhr.withCredentials = true; // This doesn't work
    },
    ...
});