如何使用凭据、HTTP 授权 (CORS) 使 XMLHttpRequest 跨域?

Posted

技术标签:

【中文标题】如何使用凭据、HTTP 授权 (CORS) 使 XMLHttpRequest 跨域?【英文标题】:How to make XMLHttpRequest cross-domain withCredentials, HTTP Authorization (CORS)? 【发布时间】:2014-03-18 00:15:23 【问题描述】:

我无法使用 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 错误。

我做错了什么?

【问题讨论】:

【参考方案1】:

我发现与preflight 请求一起使用的唯一方法是:

通过将身份验证逻辑移动到代码(例如从 Apache 到 php)来禁用 OPTIONS 方法请求的身份验证。 使用 jQuery ajax 调用 withCredentials:
$.ajax(
    type: 'POST',
    xhrFields: 
        withCredentials: true
    ,
    ...
);

令人惊讶的是,如果我只是将 xhr.withCredentials 设置为 true 它不起作用:

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

【讨论】:

【参考方案2】:

我已经 written an article 完成了 CORS 设置。

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

    如果使用凭据,Access-Control-Allow-Origin 不能是通配符。最简单的方法是将请求的Origin 标头复制到此字段。完全不清楚为什么该标准不允许使用通配符。 即使您清除缓存(可能是会话),Firefox 也会缓存访问控制结果。重新启动迫使它执行一个新的OPTIONS 请求。为了帮助调试,我添加了标题Access-Control-Max-Age: 1 open 命令的用户名/密码显然不能用作凭据。您必须自己添加 Authorization 标头。 xhr.setRequestHeader( 'Authorization', 'Basic ' + btoa( user + ':' + pass ) )

总体而言,withCredentials 系统相当脑残。简单地编写一个接受授权作为请求正文的一部分的服务器会更容易。

【讨论】:

非常感谢!过去一周,我一直在为 CORS 和用户授权而苦苦挣扎。阅读您的答案后,我决定自己进行用户授权。奇迹般有效。是的,“脑死亡”是一个非常贴切的描述。

以上是关于如何使用凭据、HTTP 授权 (CORS) 使 XMLHttpRequest 跨域?的主要内容,如果未能解决你的问题,请参考以下文章

XML-RPC:如何使过程调用可以访问登录凭据?

从 Blazor 发出 CORS 请求时如何包含凭据?

CORS“允许凭据”Nodejs/Express

无法在 CORS 请求中发送凭据

如何在 Spring Boot 2.x 中将 CORS 添加到 oauth2/resource 服务器?

无法在安全的Google Cloud Function上获得CORS错误