jQuery.getJSON - Access-Control-Allow-Origin问题

Mik*_*ike 37 javascript jquery json xmlhttprequest access-control

我正在使用jQuery的$.getJSON()函数来返回一小段JSON数据.

我已将JSON数据放在网址上,例如example.com.我没有意识到,但是当我访问相同的URL时,无法加载JSON数据.我跟着控制台,发现XMLHttpRequest由于无法加载Access-Control-Allow-Origin.

现在,我已经读完了,很多网站只是说要使用$.getJSON(),这将是解决方法,但显然它不起作用.我应该在标题或函数中更改某些内容吗?

非常感谢帮助.

Ham*_*riq 74

它很简单,使用$.getJSON()功能,在你的URL中只包括

回调=?

作为参数.这会将调用转换为进行跨域调用所必需的JSONP.更多信息:http://api.jquery.com/jQuery.getJSON/

  • 这完全取决于服务器接受额外的回调参数,它在所有情况下都可能无法执行. (21认同)
  • 这在100%的时间都不起作用,好像服务器没有设置为服务器jsonp然后它仍然返回json,在其中你将收到一个错误. (8认同)

T.J*_*der 38

你可能想要使用JSON-P(见下文).首先快速解释一下.

您提到的标题来自Cross Origin Resource Sharing标准.请注意,人们实际使用的某些浏览器不支持它,而在其他浏览器(微软,叹息)上,它需要使用特殊的对象(XDomainRequest)而不是XMLHttpRequestjQuery使用的标准.它还要求您更改服务器端资源以明确允许另一个origin(www.xxxx.com).

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

  1. 如果可能,您可以通过更正正在加载的文件的位置来实现最大兼容性,这样它们与您加载它们的文档具有相同的原点.(我假设您必须通过Ajax加载它们,因此出现同源策略问题.)

  2. 使用不受SOP约束的JSON-P.jQuery在其ajax调用中内置了对它的支持(只需设置dataType为"jsonp",jQuery将完成所有客户端工作).这需要服务器端更改,但不是很大; 基本上你生成JSON响应的只是查找一个名为"callback"的查询字符串参数,并将JSON包装在可以调用该函数的JavaScript代码中.例如,如果您当前的JSON响应是:

    {"weather": "Dreary start but soon brightening into a fine summer day."}
    
    Run Code Online (Sandbox Code Playgroud)

    您的脚本将查找"回调"查询字符串参数(假设参数的值为"jsop123")并将JSON包装在JavaScript函数调用的语法中:

    jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
    
    Run Code Online (Sandbox Code Playgroud)

    而已.JSON-P 非常兼容(因为它可以通过JavaScript script标签工作).GET但是,JSON-P仅适用于POST(因为它通过script标签工作).

  3. 使用CORS(与您引用的标题相关的机制).上面链接的规范的细节,但基本上:

    答:浏览器将使用OPTIONSHTTP谓词(方法)向您的服务器发送"预检"消息.它将包含它将使用GETPOST以及标题"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
    
    Run Code Online (Sandbox Code Playgroud)

    再次强调这是伪代码.