domínio cruzado AJAX do jQuery


477

Aqui estão duas páginas, test.php e testserver.php.

test.php

<script src="scripts/jq.js" type="text/javascript"></script>
<script>
    $(function() {
        $.ajax({url:"testserver.php",
            success:function() {
                alert("Success");
            },
            error:function() {
                alert("Error");
            },
            dataType:"json",
            type:"get"
        }
    )})
</script>

testserver.php

<?php
$arr = array("element1",
             "element2",
             array("element31","element32"));
$arr['name'] = "response";
echo json_encode($arr);
?>

Agora, meu problema: quando esses dois arquivos estão no mesmo servidor (localhost ou servidor web), ele funciona e alert("Success")é chamado; Se estiver em servidores diferentes, o que significa testingerver.php no servidor web e test.php no host local, não está funcionando e alert("Error")está em execução. Mesmo que o URL dentro do ajax seja alterado para http://domain.com/path/to/file/testserver.php


38
Para as pessoas que estão por aqui. Leia este para ter uma idéia de como cruz javascript domínio chama trabalho stackoverflow.com/a/11736771/228656
— Abdul Munim

1
Eu escrevi uma resposta para esta pergunta aqui: Carregando página html domínio cruzado com jQuery AJAX - o último, suportes https
— jherax

Respostas:


412

Use JSONP .

jQuery:

$.ajax({
     url:"testserver.php",
     dataType: 'jsonp', // Notice! JSONP <-- P (lowercase)
     success:function(json){
         // do stuff with json (in this case an array)
         alert("Success");
     },
     error:function(){
         alert("Error");
     }      
});

PHP:

<?php
$arr = array("element1","element2",array("element31","element32"));
$arr['name'] = "response";
echo $_GET['callback']."(".json_encode($arr).");";
?>

O eco pode estar errado, já faz um tempo desde que eu usei o php. Em qualquer caso, você precisa emitir callbackName('jsonString')as cotações. O jQuery passará seu próprio nome de retorno de chamada, portanto você precisa obtê-lo dos parâmetros GET.

E como Stefan Kendall postou, $ .getJSON () é um método abreviado, mas você precisa anexar 'callback=?'ao URL como parâmetro GET (sim, o valor é?, O jQuery substitui isso por seu próprio método de retorno de chamada gerado).


2
Por que você precisa retornar em callbackName('/* json */')vez de callbackName(/* json */)?
— Eric

3
@eric, o retorno de chamada espera uma string JSON. Teoricamente, um objeto também pode funcionar, mas não tem certeza de como o jQuery responde a isso, pode gerar um erro ou falhar silenciosamente.
— BGerrissen

Estou recebendo o seguinte erro. Erro de sintaxe: ausente; antes da instrução {"ResultCode": 2}. Onde {"ResultCode": 2} é a resposta. Conselho por favor.
— user2003356

@ user2003356 parece que você está retornando JSON simples em vez de JSONP. Você precisa retornar algo como: callbackFunction ({"ResultCode": 2}). O jQuery adiciona o parâmetro GET 'callback' à solicitação, esse é o nome da função de retorno de chamada que o jquery usa e deve ser adicionado à resposta.
— BGerrissen

2
É 2016. O CORS agora é um padrão amplamente suportado, em oposição ao JSONP, que só pode ser descrito como um hack. A resposta de @ joshuarh abaixo deve ser a preferida agora.
— Vicky Chijwani

202

JSONP é uma boa opção, mas existe uma maneira mais fácil. Você pode simplesmente definir o Access-Control-Allow-Origincabeçalho no seu servidor. A configuração para *aceitar solicitações AJAX entre domínios de qualquer domínio. ( https://developer.mozilla.org/en/http_access_control )

O método para fazer isso varia de idioma para idioma, é claro. Aqui está no Rails:

class HelloController < ApplicationController
  def say_hello
    headers['Access-Control-Allow-Origin'] = "*"
    render text: "hello!"
  end
end

Neste exemplo, a say_helloação aceitará solicitações AJAX de qualquer domínio e retornará uma resposta "Olá!".

Aqui está um exemplo dos cabeçalhos que podem retornar:

HTTP/1.1 200 OK 
Access-Control-Allow-Origin: *
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: text/html; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "c4ca4238a0b923820dcc509a6f75849b"
X-Runtime: 0.913606
Content-Length: 6
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Thu, 01 Mar 2012 20:44:28 GMT
Connection: Keep-Alive

Por mais fácil que seja, ele tem algumas limitações no navegador. Consulte http://caniuse.com/#feat=cors .


12
Jsonp não suportava postar, colocar e excluir. Sua solução funciona muito bem.
— 21412 TonyTakeshi

35
no cabeçalho do PHP ("Access-Control-Allow-Origin: *");
— SparK

9
@Warrior Se você estiver usando o .post()método jQuery, precisará ativar o suporte entre domínios no jQuery. É feito com isto: $.support.cors = true.
— precisa

21
Quais são as implicações de segurança da configuração de um servidor dessa maneira?
— Jon Schneider

19
Seria melhor permitir apenas os domínios com os quais você deseja compartilhar os dados, em vez de usar o wilcard "*".
— Sebastián Grignoli

32

Você pode controlar isso via cabeçalho HTTP adicionando Access-Control-Allow-Origin . A configuração como * aceitará solicitações AJAX entre domínios de qualquer domínio.

Usando o PHP é muito simples, basta adicionar a seguinte linha ao script que você deseja acessar fora do seu domínio:

header("Access-Control-Allow-Origin: *");

Não se esqueça de ativar o módulo mod_headers no httpd.conf.


você salvou meu dia.
— NomanJaved

20

Você precisa dar uma olhada na mesma política de origem :

Na computação, a mesma política de origem é um conceito de segurança importante para várias linguagens de programação do navegador, como JavaScript. A política permite que scripts em execução nas páginas originárias do mesmo site acessem os métodos e propriedades um do outro sem restrições específicas, mas impede o acesso à maioria dos métodos e propriedades nas páginas de sites diferentes.

Para que você possa obter dados, é necessário:

Mesmo protocolo e host

Você precisa implementar o JSONP para contorná -lo.


17

Eu tive que carregar a página do disco local "file: /// C: /test/htmlpage.html", chamar "URL http: //localhost/getxml.php" e fazer isso nos navegadores IE8 + e Firefox12 +, use o jQuery v1 .7.2 lib para minimizar o código padrão. Depois de ler dezenas de artigos, finalmente entendi. Aqui está o meu resumo.

  • O script do servidor (.php, .jsp, ...) deve retornar o cabeçalho de resposta http Access-Control-Allow-Origin: *
  • antes de usar o jQuery ajax, defina esse sinalizador em javascript: jQuery.support.cors = true;
  • você pode definir o sinalizador uma vez ou todas as vezes antes de usar a função jQuery ajax
  • agora eu posso ler o documento .xml no IE e Firefox. Outros navegadores que não testei.
  • O documento de resposta pode ser sem formatação / texto, xml, json ou qualquer outra coisa

Aqui está um exemplo de chamada ajax do jQuery com alguns sysouts de depuração.

jQuery.support.cors = true;
$.ajax({
    url: "http://localhost/getxml.php",
    data: { "id":"doc1", "rows":"100" },
    type: "GET",
    timeout: 30000,
    dataType: "text", // "xml", "json"
    success: function(data) {
        // show text reply as-is (debug)
        alert(data);

        // show xml field values (debug)
        //alert( $(data).find("title").text() );

        // loop JSON array (debug)
        //var str="";
        //$.each(data.items, function(i,item) {
        //  str += item.title + "\n";
        //});
        //alert(str);
    },
    error: function(jqXHR, textStatus, ex) {
        alert(textStatus + "," + ex + "," + jqXHR.responseText);
    }
});

1
Eu escrevi uma resposta para esta pergunta aqui: Carregando página html domínio cruzado com jQuery AJAX - o último, suportes https
— jherax

Para o ponto mais importante: no PHP, adicione esta linha ao script:header("Access-Control-Allow-Origin: *");
— T30

1
@whome muito obrigado pela sua resposta. Você me ajudou muito. Felicidades.
— Luis Milanese

10

É verdade que a política de mesma origem impede que o JavaScript faça solicitações entre domínios, mas a especificação CORS permite exatamente o tipo de acesso à API que você está procurando e é suportada pelo lote atual dos principais navegadores.

Veja como habilitar o compartilhamento de recursos de origem cruzada para cliente e servidor:

http://enable-cors.org/

"O CORS (compartilhamento de recursos de origem cruzada) é uma especificação que permite acesso verdadeiramente aberto através dos limites do domínio. Se você exibir conteúdo público, considere usar o CORS para abri-lo para acesso universal a JavaScript / navegador".



9

Eu uso o servidor Apache, então usei o módulo mod_proxy. Ativar módulos:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Adicione então:

ProxyPass /your-proxy-url/ http://service-url:serviceport/

Por fim, passe o proxy-url para o seu script.




4

Nos documentos do Jquery ( link ):

  • Devido a restrições de segurança do navegador, a maioria das solicitações "Ajax" está sujeita à mesma política de origem; a solicitação não pode recuperar dados de um domínio, subdomínio ou protocolo diferente.

  • As solicitações de script e JSONP não estão sujeitas às mesmas restrições de política de origem.

Então, eu presumo que você precisa usar o jsonp para a solicitação. Mas não tentei isso sozinho.


2

Conheço três maneiras de resolver seu problema:

  1. Primeiro, se você tiver acesso aos dois domínios, poderá permitir o acesso a todos os outros domínios usando:

    header("Access-Control-Allow-Origin: *");

    ou apenas um domínio adicionando o código abaixo ao arquivo .htaccess:

    <FilesMatch "\.(ttf|otf|eot|woff)$"> <IfModule mod_headers.c> SetEnvIf Origin "http(s)?://(www\.)?(google.com|staging.google.com|development.google.com|otherdomain.net|dev02.otherdomain.net)$" AccessControlAllowOrigin=$0 Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin </IfModule> </FilesMatch>

  2. você pode ter uma solicitação ajax para um arquivo php no seu servidor e manipular a solicitação para outro domínio usando esse arquivo php.

  3. você pode usar o jsonp, porque ele não precisa de permissão. para isso, você pode ler a resposta do nosso amigo @BGerrissen.

0

Para o Microsoft Azure, é um pouco diferente.

O Azure tem uma configuração especial do CORS que precisa ser definida. É essencialmente a mesma coisa nos bastidores, mas simplesmente definir o cabeçalho que joshuarh menciona não funcionará. A documentação do Azure para habilitar vários domínios pode ser encontrada aqui:

https://docs.microsoft.com/en-us/azure/app-service-api/app-service-api-cors-consume-javascript

Eu brinquei com isso por algumas horas antes de perceber que minha plataforma de hospedagem tinha essa configuração especial.


0

funciona, tudo que você precisa:

PHP:

header('Access-Control-Allow-Origin: http://www.example.com');
header("Access-Control-Allow-Credentials: true");
header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');

JS (jQuery ajax):

var getWBody = $.ajax({ cache: false,
        url: URL,
        dataType : 'json',
        type: 'GET',
        xhrFields: { withCredentials: true }
});
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.