jQuery、CORS、JSON(无填充)和身份验证问题
Posted
技术标签:
【中文标题】jQuery、CORS、JSON(无填充)和身份验证问题【英文标题】:jQuery, CORS, JSON (without padding) and authentication issues 【发布时间】:2012-06-27 07:18:00 【问题描述】:我有两个域。我正在尝试通过另一个域上的页面从一个域访问 JSON 对象。我已经阅读了有关此问题的所有内容,但仍然无法弄清楚。
为 JSON 提供服务的域具有以下设置:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, OPTIONS"
Header set Access-Control-Allow-Headers "origin, authorization, accept"
在我的另一个域中,我正在调用以下内容:
$.ajax(
type:'get',
beforeSend: function(xhr)
var auth = // authentication;
xhr.setRequestHeader("Authorization", "Basic " + auth);
url:myUrl,
dataType:'json',
error: function(xhr, textStatus, errorThrown) console.log(textStatus, errorThrown);
)
我知道“auth”已正确初始化(记录并检查)。但是,这不起作用。在 Firefox 的控制台中,我得到 请求网址:...
Request Method:
OPTIONS
Status Code:
HTTP/1.1 401 Authorization Required
如果我去掉 beforeSend:...
部分,我会看到以下内容
Request Method:
GET
Status Code:
HTTP/1.1 401 Authorization Required
但是,提供 JSON 的域也可以提供 JSONP。我不想使用这个,主要是因为应用程序会在专用浏览器上不断运行,我很担心this issue。更重要的是,我真的很想知道我所做的事情到底出了什么问题。我知道出于实际目的,有多种方法可以克服 JSONP 内存泄漏(例如不使用 jQuery)。
无论如何,当我使用 JSONP 时,我的代码如下所示:
$.ajax(
url:newUrl,
dataType:'jsonp',
jsonp:'jsonp'
).done(function(d)console.log(d))
这会得到以下结果
Request Method:
GET
Status Code:
HTTP/1.1 200 OK
在它提示我输入用户名和密码的警告框之后。
jQuery 处理 JSONP 请求的方式与 JSON 请求的方式有根本的区别吗?如果是这样,我该如何解决这个问题?
谢谢。
编辑:这是我找到的。
基本上,因为我需要身份验证,所以 GET 请求正在发送一个 Authorization 标头。但是,这不是一个“简单”的标头,因此浏览器正在发送一个飞行前请求(OPTIONS)。但是,此预检请求没有任何身份验证,因此服务器拒绝了它。 “解决方案”是设置服务器让 OPTIONS 请求不需要身份验证,并向其报告 HTTP 状态 200。
参考:http://www.kinvey.com/blog/item/61-kinvey-adds-cross-origin-resource-sharing-cors
mail-archive[.com]/c-user@axis.apache.org/msg00790.html(不允许发布更多链接)
不幸的是,“解决方案”仅适用于 Firefox,不适用于 Chrome。 Chrome 只是将请求显示为红色,但没有向我提供有关失败原因的更多信息。
编辑 2:在 Chrome 上已修复:我尝试从中获取数据的服务器具有不受信任的安全证书。因此,Chrome 上的预检请求失败。解决方案 superuser[.com]/questions/27268/how-do-i-disable-the-warning-chrome-gives-if-a-security-certificate-is-not-trust(不允许发布更多链接)
【问题讨论】:
我认为:jQuery JSONP 将数据作为外部 javascript 加载(在<header>
中添加 <script>
标签)并运行临时生成的 jQuery 函数来解析传入的数据 Array
一次加载。 jQuery JSON 将数据作为 XHR 请求加载为期望 JSON 对象作为结果(因此它不会作为 <script>
加载),当跨不同来源加载时将失败并出现 CORS 错误,因此无法弹出您的用户/pass 警告框。
我很确定 JSON 加载会进行预取,如果跨域加载将会失败。所以你可能没有通过预取。
***.com/questions/9559947/…
可能是您将 user:pasdwd 编码为 base64 错误?
@potench:我认为这是真正的原因。似乎如果加载了
【参考方案1】:
Some examples available here 可以进一步说明访问控制如何与 CORS 相结合。特别是经过认证的 GET 示例。访问控制要求请求将XMLHttpRequest
上的withCredentials
标志设置为true
,并让处理OPTIONS
方法的服务器做两件事:
-
设置
Access-Control-Allow-Credentials: true
不要在Access-Control-Allow-Origin
标头中使用通配符*
。这必须完全根据 HTTP 访问控制 (CORS) 上的 MDN docs 设置为原点。
本质上,处理 OPTIONS 请求的事物需要发回适当的响应标头,以便您可以发出该凭证请求。
在您的问题中,您说您正在与之交互的服务正在返回Access-Control-Allow-Origin: *
,这与凭据跨域请求不兼容。这需要专门返回原点。
上述 MDN Http 访问控制 (CORS) 文档还链接到服务器端访问控制文档,该文档概述了服务器可能如何响应各种跨域请求 - 包括处理需要您发回的跨域凭据 POST 请求响应 OPTIONS 方法的正确标头。 You can find that example here。
【讨论】:
【参考方案2】:Welp,现在我已经有足够的代表一段时间了,我不妨回答这个问题并接受它。
当您尝试向带有标头的服务器发送GET
json 请求时,浏览器首先发送OPTION
请求以确保您可以访问它。不幸的是,这个OPTION
请求不能携带任何身份验证。这意味着如果你想发送一个带有身份验证的GET
,服务器必须允许一个选项没有身份验证。一旦我这样做了,事情就开始起作用了。
【讨论】:
你是怎么做到的?我遇到了类似的问题,但有一个 POST 请求。它返回 OPTIONS 和 401 Authorization Required。 就我而言,我能够修改服务器以允许未经身份验证的 OPTION 请求,但我不确定是否有更好的方法... 你是如何修改服务器的?有 apache 配置吗? 我不记得我到底做了什么(事实上,我认为同事可能已经在服务器端修复了它),但serverfault.com/questions/231766/… 可能会有所帮助?【参考方案3】:您为什么不尝试在浏览器中输入要从中获取 JSON 的 URL 并看看会发生什么。听起来您实际上只需要对这个其他网站进行身份验证即可访问它。
如果您的网站需要在 IE 等其他浏览器中运行,顺便说一下,您将需要 JSONP。安全性不允许跨站点请求工作。标题不会改变这一点。我相信您还需要在标题中添加安全策略。
【讨论】:
试过了。转到 URL 会弹出一个警报,询问用户名和密码,但没有 jsonp 的 get 请求不会。我不需要 IE 支持。不过感谢您的帮助...还有其他想法吗?以上是关于jQuery、CORS、JSON(无填充)和身份验证问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 JQuery 在 Internet Explorer 中进行 CORS 身份验证
尝试使用 json 数据而不是纯文本或 x-www-form-urlencoded 进行 JQuery 发布时出现 CORS 问题