Javascript jQuery.getJSON - 访问控制允许来源问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6396623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery.getJSON - Access-Control-Allow-Origin Issue
提问by Mike
I'm jusing jQuery's $.getJSON()
function to return a short set of JSON data.
我正在使用 jQuery 的$.getJSON()
函数来返回一组简短的 JSON 数据。
I've got the JSON data sitting on a url such as example.com
.
I didn't realize it, but as I was accessing that same url, the JSON data couldn't be loaded. I followed through the console and found that XMLHttpRequest
couldn't load due to Access-Control-Allow-Origin
.
我将 JSON 数据放在一个 url 上,例如example.com
. 我没有意识到,但是当我访问同一个 url 时,无法加载 JSON 数据。我跟踪控制台,发现XMLHttpRequest
由于Access-Control-Allow-Origin
.
Now, I've read through, a lot of sites that just said to use $.getJSON()
and that would be the work around, but obviously it didn't work. Is there something I should change in the headers or in the function?
现在,我已经通读了很多网站,这些网站都说可以使用$.getJSON()
,这将是解决方法,但显然它不起作用。我应该在标题或函数中更改某些内容吗?
Help is greatly appreciated.
非常感谢帮助。
回答by Hammad Tariq
It's simple, use $.getJSON()
function and in your URL just include
很简单,使用$.getJSON()
函数,在你的 URL 中只包含
callback=?
回调=?
as a parameter. That will convert the call to JSONP which is necessary to make cross-domain calls. More info: http://api.jquery.com/jQuery.getJSON/
作为参数。这会将调用转换为 JSONP,这是进行跨域调用所必需的。更多信息:http: //api.jquery.com/jQuery.getJSON/
回答by T.J. Crowder
You may well want to use JSON-P instead (see below). First a quick explanation.
您可能想改用 JSON-P(见下文)。首先快速解释一下。
The header you've mentioned is from the Cross Origin Resource Sharingstandard. Beware that it is not supportedby some browsers people actually use, and on other browsers (Microsoft's, sigh) it requires using a special object (XDomainRequest
) rather than the standard XMLHttpRequest
that jQuery uses. It also requires that you change server-side resources to explicitly allow the other origin (www.xxxx.com
).
您提到的标头来自跨源资源共享标准。请注意,人们实际使用的某些浏览器不支持它,而在其他浏览器(Microsoft 的,叹气)上,它需要使用特殊对象 ( XDomainRequest
) 而不是XMLHttpRequest
jQuery 使用的标准。它还要求您更改服务器端资源以明确允许其他来源 ( www.xxxx.com
)。
To get the JSON data you're requesting, you basically have three options:
要获取您请求的 JSON 数据,您基本上有三个选项:
If possible, you can be maximally-compatible by correcting the location of the files you're loading so they have the same origin as the document you're loading them into. (I assume you must be loading them via Ajax, hence the Same Origin Policyissue showing up.)
Use JSON-P, which isn't subject to the SOP. jQuery has built-in support for it in its
ajax
call (just setdataType
to "jsonp" and jQuery will do all the client-side work). This requires server side changes, but not very big ones; basically whatever you have that's generating the JSON response just looks for a query string parameter called "callback" and wraps the JSON in JavaScript code that would call that function. E.g., if your current JSON response is:{"weather": "Dreary start but soon brightening into a fine summer day."}
Your script would look for the "callback" query string parameter (let's say that the parameter's value is "jsop123") and wraps that JSON in the syntax for a JavaScript function call:
jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
That's it. JSON-P is verybroadly compatible (because it works via JavaScript
script
tags). JSON-P is only forGET
, though, notPOST
(again because it works viascript
tags).Use CORS (the mechanism related to the header you quoted). Details in the specification linked above, but basically:
A. The browser will send your server a "preflight" message using the
OPTIONS
HTTP verb (method). It will contain the various headers it would send with theGET
orPOST
as well as the headers "Origin", "Access-Control-Request-Method" (e.g.,GET
orPOST
), and "Access-Control-Request-Headers" (the headers it wants to send).B. Your PHP decides, based on that information, whether the request is okay and if so responds with the "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", and "Access-Control-Allow-Headers" headers with the values it will allow. You don't send any body (page) with that response.
C. The browser will look at your response and see whether it's allowed to send you the actual
GET
orPOST
. If so, it will send that request, again with the "Origin" and various "Access-Control-Request-xyz" headers.D. Your PHP examines those headers againto make sure they're still okay, and if so responds to the request.
In pseudo-code (I haven't done much PHP, so I'm not trying to do PHP syntax here):
// Find out what the request is asking for corsOrigin = get_request_header("Origin") corsMethod = get_request_header("Access-Control-Request-Method") corsHeaders = get_request_header("Access-Control-Request-Headers") if corsOrigin is null or "null" { // Requests from a `file://` path seem to come through without an // origin or with "null" (literally) as the origin. // In my case, for testing, I wanted to allow those and so I output // "*", but you may want to go another way. corsOrigin = "*" } // Decide whether to accept that request with those headers // If so: // Respond with headers saying what's allowed (here we're just echoing what they // asked for, except we may be using "*" [all] instead of the actual origin for // the "Access-Control-Allow-Origin" one) set_response_header("Access-Control-Allow-Origin", corsOrigin) set_response_header("Access-Control-Allow-Methods", corsMethod) set_response_header("Access-Control-Allow-Headers", corsHeaders) if the HTTP request method is "OPTIONS" { // Done, no body in response to OPTIONS stop } // Process the GET or POST here; output the body of the response
Again stressing that this is pseudo-code.
如果可能,您可以通过更正正在加载的文件的位置来最大程度地兼容,以便它们与您将它们加载到的文档具有相同的来源。(我假设您必须通过 Ajax 加载它们,因此出现了同源策略问题。)
使用不受 SOP 约束的JSON-P。jQuery 在其
ajax
调用中内置了对它的支持(只需设置dataType
为“jsonp”,jQuery 将完成所有客户端工作)。这需要服务器端更改,但不是很大;基本上,无论您拥有什么生成 JSON 响应,只需查找名为“回调”的查询字符串参数,并将 JSON 包装在将调用该函数的 JavaScript 代码中。例如,如果您当前的 JSON 响应是:{"weather": "Dreary start but soon brightening into a fine summer day."}
您的脚本将查找“回调”查询字符串参数(假设该参数的值为“jsop123”)并将该 JSON 包装在 JavaScript 函数调用的语法中:
jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
就是这样。JSON-P 具有非常广泛的兼容性(因为它通过 JavaScript
script
标签工作)。JSON-P 仅适用于GET
,但不是POST
(再次因为它通过script
标签工作)。使用 CORS(与您引用的标头相关的机制)。上面链接的规范中的详细信息,但基本上:
A. 浏览器将使用
OPTIONS
HTTP 动词(方法)向您的服务器发送“预检”消息。它将包含它将与GET
或一起发送的各种标头POST
以及标头“Origin”、“Access-Control-Request-Method”(例如,GET
或POST
)和“Access-Control-Request-Headers”(它的标头)想送)。B. 您的 PHP 会根据该信息决定请求是否正常,如果正常则以“Access-Control-Allow-Origin”、“Access-Control-Allow-Methods”和“Access-Control-Allow-标头”标头及其允许的值。您不会随该响应发送任何正文(页面)。
C. 浏览器将查看您的响应,看看是否允许向您发送实际
GET
或POST
. 如果是这样,它将再次发送该请求,并带有“Origin”和各种“Access-Control-Request-xyz”标头。D. 您的 PHP再次检查这些标头以确保它们仍然正常,如果是,则响应请求。
在伪代码中(我没有做过太多 PHP,所以我不想在这里做 PHP 语法):
// Find out what the request is asking for corsOrigin = get_request_header("Origin") corsMethod = get_request_header("Access-Control-Request-Method") corsHeaders = get_request_header("Access-Control-Request-Headers") if corsOrigin is null or "null" { // Requests from a `file://` path seem to come through without an // origin or with "null" (literally) as the origin. // In my case, for testing, I wanted to allow those and so I output // "*", but you may want to go another way. corsOrigin = "*" } // Decide whether to accept that request with those headers // If so: // Respond with headers saying what's allowed (here we're just echoing what they // asked for, except we may be using "*" [all] instead of the actual origin for // the "Access-Control-Allow-Origin" one) set_response_header("Access-Control-Allow-Origin", corsOrigin) set_response_header("Access-Control-Allow-Methods", corsMethod) set_response_header("Access-Control-Allow-Headers", corsHeaders) if the HTTP request method is "OPTIONS" { // Done, no body in response to OPTIONS stop } // Process the GET or POST here; output the body of the response
再次强调这是伪代码。