Carregando o ponto de extremidade entre domínios com o AJAX


131

Estou tentando carregar uma página HTML entre domínios usando AJAX, mas, a menos que o dataType seja "jsonp", não consigo obter uma resposta. No entanto, usando jsonp, o navegador espera um tipo de script mime, mas recebe "text / html".

Meu código para a solicitação é:

$.ajax({
    type: "GET",
    url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute",
    dataType: "jsonp",
}).success( function( data ) {
    $( 'div.ajax-field' ).html( data );
});

Existe alguma maneira de evitar o uso do jsonp para a solicitação? Eu já tentei usar o parâmetro crossDomain, mas não funcionou.

Caso contrário, existe alguma maneira de receber o conteúdo html no jsonp? Atualmente, o console está dizendo "inesperado <" na resposta jsonp.


Resolvi o problema criando um proxy.php, conforme explicado aqui. Scode7.blogspot.com/2019/11/…
#

Respostas:


235

jQuery Ajax Notes

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

Existem algumas maneiras de superar a barreira entre domínios :

Existem alguns plugins que ajudam com solicitações entre domínios :

Atenção!

A melhor maneira de superar esse problema é criando seu próprio proxy no back-end, para que o seu proxy aponte para os serviços em outros domínios, porque no back-end não existe a mesma restrição de política de origem . Mas se você não pode fazer isso no back-end, preste atenção às dicas a seguir.


Aviso!

O uso de proxies de terceiros não é uma prática segura, pois eles podem acompanhar seus dados, para que possam ser usados ​​com informações públicas, mas nunca com dados privados.


Os exemplos de código mostrados abaixo usam jQuery.get () e jQuery.getJSON () , ambos são métodos abreviados de jQuery.ajax ()


CORS Anywhere

O CORS Anywhere é um proxy node.js que adiciona cabeçalhos CORS à solicitação em proxy.
Para usar a API, basta prefixar o URL com o URL da API. (Suporta https : consulte o repositório do github )

Se você deseja ativar automaticamente solicitações entre domínios, quando necessário, use o seguinte snippet:

$.ajaxPrefilter( function (options) {
  if (options.crossDomain && jQuery.support.cors) {
    var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
    options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
    //options.url = "http://cors.corsproxy.io/url=" + options.url;
  }
});

$.get(
    'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


Qualquer Origem

Qualquer que seja a origem, é um acesso jsonp entre domínios . Esta é uma alternativa de código aberto ao anyorigin.com .

Para buscar os dados do google.com, você pode usar este snippet:

// It is good specify the charset you expect.
// You can use the charset you want instead of utf-8.
// See details for scriptCharset and contentType options: 
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
$.ajaxSetup({
    scriptCharset: "utf-8", //or "ISO-8859-1"
    contentType: "application/json; charset=utf-8"
});

$.getJSON('http://whateverorigin.org/get?url=' + 
    encodeURIComponent('http://google.com') + '&callback=?',
    function (data) {
        console.log("> ", data);

        //If the expected response is text/plain
        $("#viewer").html(data.contents);

        //If the expected response is JSON
        //var response = $.parseJSON(data.contents);
});


Proxy CORS

O Proxy CORS é um proxy node.js simples para ativar a solicitação do CORS para qualquer site. Ele permite que o código javascript no seu site acesse recursos em outros domínios que normalmente seriam bloqueados devido à política de mesma origem.

Como funciona? O Proxy CORS aproveita o Compartilhamento de Recursos de Origem Cruzada, um recurso que foi adicionado juntamente com o HTML 5. Os servidores podem especificar que desejam que os navegadores permitam que outros sites solicitem os recursos que hospedam. O Proxy CORS é simplesmente um Proxy HTTP que adiciona um cabeçalho às respostas dizendo "qualquer pessoa pode solicitar isso".

Essa é outra maneira de atingir a meta (consulte www.corsproxy.com ). Tudo o que você precisa fazer é retirar o http: // e o www. a partir do URL que está sendo enviado por proxy e preceda o URL comwww.corsproxy.com/

$.get(
    'http://www.corsproxy.com/' +
    'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
    function (response) {
        console.log("> ", response);
        $("#viewer").html(response);
});


Navegador proxy CORS

Recentemente eu encontrei este, envolve vários utilitários de compartilhamento remoto de origem cruzada, orientados para a segurança. Mas é uma caixa preta com o Flash como back-end.

Você pode vê-lo em ação aqui: Navegador proxy CORS
Obtenha o código-fonte no GitHub: koto / cors-proxy-browser


4
Você também pode implantar sua própria versão do WhateverOrigin.org (ou portar o código para seu próprio uso) a partir daqui: github.com/ripper234/Whatever-Origin
EpicVoyage

1
Imagens, CSS e javascript externo pode ser referenciado a partir de outra origem, assim, na resposta que você pode passar por cima da string HTML e substituir o src de recursos externos
jherax

1
oi jherax eu usei o whatorigin para obter uma página html (só funcionou para mim, usei o yql, o google etc), mas caracteres não ingleses são estranhos. tentou data.contents codificar, mas não ajudou
user217648

1
Olá @Miru, como o título diz: "Carregando a página html entre domínios com o jQuery AJAX", respondi ao título fornecendo alguns exemplos usando um proxy para executar solicitações entre domínios. Além disso, em resposta à redação da pergunta, forneci alguns links para fazer solicitações entre domínios usando JSONP com YQL. Convido você a ler os links, eles são muito úteis.
jherax

1
Acabou usando o método CORS Anywhere com oe $.ajaxPrefilterfuncionou muito bem. Muito Obrigado!
Joshua Pinter

24

Você pode usar um plug-in jQuery de origem cruzada Ajax. Com este plugin, você usa jQuery.ajax()vários domínios. Ele usa os serviços do Google para conseguir isso:

O plug-in AJAX Cross Origin usa o Google Apps Script como um proxy jSON getter em que o jSONP não está implementado. Quando você define a opção crossOrigin como true, o plug-in substitui o URL original pelo endereço de script do Google Apps e o envia como parâmetro de URL codificado. O script do Google Apps usa os recursos dos servidores do Google para obter os dados remotos e devolvê-los ao cliente como JSONP.

É muito simples de usar:

    $.ajax({
        crossOrigin: true,
        url: url,
        success: function(data) {
            console.log(data);
        }
    });

Você pode ler mais aqui: http://www.ajax-cross-origin.com/


22
Para mim, este plugin nunca funcionou. Não faz nada no Chrome.
Michael

Como posso me autenticar no servidor?
Sttaq 23/04

funciona bem! A API que estou usando não suporta JSONP nem CORS, portanto, essa é a única coisa que funcionou. Muito obrigado!
JP Lew

A crossOriginopção do jQuery certamente não faz nada para mitigar políticas de mesma origem. Eu apagar esta resposta se eu pudesse
Phil

13

Se o site externo não suportar JSONP ou CORS, sua única opção é usar um proxy.

Crie um script em seu servidor que solicite esse conteúdo e use o jQuery ajax para acessar o script em seu servidor.


5

Basta colocar isso no cabeçalho da sua página PHP e ele funcionará sem a API:

header('Access-Control-Allow-Origin: *'); //allow everybody  

ou

header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain 

ou

$http_origin = $_SERVER['HTTP_ORIGIN'];  //allow multiple domains

$allowed_domains = array(
  'http://codesheet.org',
  'http://stackoverflow.com'
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

Eu estou querendo saber de onde $_SERVER['HTTP_ORIGIN']vem. Não consegui encontrá-lo na documentação do PHP ou em qualquer outro lugar.
Zsolti 17/01/19

Hmm, parece que ele é preenchido apenas com solicitações AJAX. De qualquer forma, obrigado pela resposta.
Zsolti 17/01/19

0

Estou postando isso no caso de alguém enfrentar o mesmo problema que estou enfrentando agora. Eu tenho uma impressora térmica Zebra, equipada com o servidor de impressão ZebraNet, que oferece uma interface de usuário baseada em HTML para editar várias configurações, ver o status atual da impressora etc. Eu preciso obter o status da impressora, que é exibido em uma dessas páginas html, oferecidas pelo servidor ZebraNet e, por exemplo, alertar () uma mensagem para o usuário no navegador. Isso significa que eu tenho que obter essa página html em Javascript primeiro. Embora a impressora esteja na LAN do PC do usuário, essa mesma política de origemainda permanece firme no meu caminho. Eu tentei o JSONP, mas o servidor retorna html e não encontrei uma maneira de modificar sua funcionalidade (se pudesse, eu já teria definido o cabeçalho mágico Access-control-allow-origin: *). Então, decidi escrever um pequeno aplicativo de console em C #. Ele deve ser executado como administrador para funcionar corretamente; caso contrário, ele trollará: D uma exceção. Aqui está um código:

// Create a listener.
        HttpListener listener = new HttpListener();
        // Add the prefixes.
        //foreach (string s in prefixes)
        //{
        //    listener.Prefixes.Add(s);
        //}
        listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere,
        //because the printer is accessible only within the LAN (no portforwarding)
        listener.Start();
        Console.WriteLine("Listening...");
        // Note: The GetContext method blocks while waiting for a request. 
        HttpListenerContext context;
        string urlForRequest = "";

        HttpWebRequest requestForPage = null;
        HttpWebResponse responseForPage = null;
        string responseForPageAsString = "";

        while (true)
        {
            context = listener.GetContext();
            HttpListenerRequest request = context.Request;
            urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent
            Console.WriteLine(urlForRequest);

            //Request for the html page:
            requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest);
            responseForPage = (HttpWebResponse)requestForPage.GetResponse();
            responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd();

            // Obtain a response object.
            HttpListenerResponse response = context.Response;
            // Send back the response.
            byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString);
            // Get a response stream and write the response to it.
            response.ContentLength64 = buffer.Length;
            response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D
            System.IO.Stream output = response.OutputStream;
            output.Write(buffer, 0, buffer.Length);
            // You must close the output stream.
            output.Close();
            //listener.Stop();

Tudo o que o usuário precisa fazer é executar esse aplicativo de console como administrador. Sei que é muito ... frustrante e complicado, mas é uma solução alternativa para o problema da Diretiva de Domínio, caso você não possa modificar o servidor de nenhuma maneira.

edit: from js eu faço uma simples chamada ajax:

$.ajax({
                type: 'POST',
                url: 'http://LAN_IP:1234/http://google.com',
                success: function (data) {
                    console.log("Success: " + data);
                },
                error: function (e) {
                    alert("Error: " + e);
                    console.log("Error: " + e);
                }
            });

O html da página solicitada é retornado e armazenado na variável de dados .


0

Para obter o site externo do formulário de dados passando usando um proxy local, conforme sugerido por jherax, você pode criar uma página php que busca o conteúdo para você a partir do respectivo URL externo e enviar uma solicitação de obtenção para essa página php.

var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
   alert(req.responseText);
}

como um proxy php, você pode usar https://github.com/cowboy/php-simple-proxy


0

Seu URLnão funciona atualmente, mas seu código pode ser atualizado com esta solução de trabalho:

var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P@ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";

url = 'https://google.com'; // TEST URL

$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
    $('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


-2

Você precisa do proxy CORS que proxies sua solicitação do navegador para o serviço solicitado com os cabeçalhos CORS apropriados . A lista desses serviços está no snippet de código abaixo. Você também pode executar o snippet de código fornecido para ver o ping nesses serviços a partir da sua localização.

$('li').each(function() {
  var self = this;
  ping($(this).text()).then(function(delta) {
    console.log($(self).text(), delta, ' ms');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script>
<ul>
  <li>https://crossorigin.me/</li>
  <li>https://cors-anywhere.herokuapp.com/</li>
  <li>http://cors.io/</li>
  <li>https://cors.5apps.com/?uri=</li>
  <li>http://whateverorigin.org/get?url=</li>
  <li>https://anyorigin.com/get?url=</li>
  <li>http://corsproxy.nodester.com/?src=</li>
  <li>https://jsonp.afeld.me/?url=</li>
  <li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li>
</ul>


11
Isso não responde à pergunta de forma alguma.
0xc0de 6/09/16

@ 0xc0de eu finalmente escrevi a resposta.
precisa saber é o seguinte

-7

Descobri isso. Usou isso em seu lugar.

$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');

O código que você usou lá é irrelevante. O que importa são os cabeçalhos CORS do servidor.
Quentin
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.