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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:32:51  来源:igfitidea点击:

jQuery.getJSON - Access-Control-Allow-Origin Issue

javascriptjqueryjsonxmlhttprequestaccess-control

提问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 XMLHttpRequestcouldn'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 XMLHttpRequestthat jQuery uses. It also requires that you change server-side resources to explicitly allow the other origin (www.xxxx.com).

您提到的标头来自跨源资源共享标准。请注意,人们实际使用的某些浏览器不支持它,而在其他浏览器(Microsoft 的,叹气)上,它需要使用特殊对象 ( XDomainRequest) 而不是XMLHttpRequestjQuery 使用的标准。它还要求您更改服务器端资源以明确允许其他来源 ( www.xxxx.com)。

To get the JSON data you're requesting, you basically have three options:

要获取您请求的 JSON 数据,您基本上有三个选项:

  1. 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.)

  2. Use JSON-P, which isn't subject to the SOP. jQuery has built-in support for it in its ajaxcall (just set dataTypeto "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 scripttags). JSON-P is only for GET, though, not POST(again because it works via scripttags).

  3. 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 OPTIONSHTTP verb (method). It will contain the various headers it would send with the GETor POSTas well as the headers "Origin", "Access-Control-Request-Method" (e.g., GETor POST), 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 GETor POST. 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.

  1. 如果可能,您可以通过更正正在加载的文件的位置来最大程度地兼容,以便它们与您将它们加载到的文档具有相同的来源。(我假设您必须通过 Ajax 加载它们,因此出现了同源策略问题。)

  2. 使用不受 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 具有非常广泛的兼容性(因为它通过 JavaScriptscript标签工作)。JSON-P 仅适用于GET,但不是POST(再次因为它通过script标签工作)。

  3. 使用 CORS(与您引用的标头相关的机制)。上面链接的规范中的详细信息,但基本上:

    A. 浏览器将使用OPTIONSHTTP 动词(方法)向您的服务器发送“预检”消息。它将包含它将与GET或一起发送的各种标头POST以及标头“Origin”、“Access-Control-Request-Method”(例如,GETPOST)和“Access-Control-Request-Headers”(它的标头)想送)。

    B. 您的 PHP 会根据该信息决定请求是否正常,如果正常则以“Access-Control-Allow-Origin”、“Access-Control-Allow-Methods”和“Access-Control-Allow-标头”标头及其允许的值。您不会随该响应发送任何正文(页面)。

    C. 浏览器将查看您的响应,看看是否允许向您发送实际GETPOST. 如果是这样,它将再次发送该请求,并带有“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
    

    再次强调这是伪代码。