Błąd Access-Control-Allow-Origin podczas wysyłania posta jQuery do Google API

143

Dużo czytam o błędzie „Access-Control-Allow-Origin”, ale nie rozumiem, co mam naprawić :(

Gram z Google Moderator API, ale kiedy próbuję dodać nową serię , otrzymuję:

XMLHttpRequest cannot load 
https://www.googleapis.com/moderator/v1/series?key=[key]
&data%5Bdescription%5D=Share+and+rank+tips+for+eating+healthily+on+the+cheaps!
&data%5Bname%5D=Eating+Healthy+%26+Cheap
&data%5BvideoSubmissionAllowed%5D=false. 
Origin [my_domain] is not allowed by Access-Control-Allow-Origin.

Próbowałem z parametrem callback i bez niego, próbowałem dodać „Access-Control-Allow-Origin *” do nagłówka. I nie wiem, jak tutaj używać $ .getJSON, jeśli się aplikuję, ponieważ muszę dodać nagłówek Authorization i nie wiem, jak to zrobić bez wcześniejszego połączenia z $ .ajax: /

Jakieś światło dla tej ciemności uu?

To jest kod:

<script src="http://www.google.com/jsapi"></script>

<script type="text/javascript">

var scope = "https://www.googleapis.com/auth/moderator";
var token = '';

function create(){
     if (token == '')
      token = doCheck();

     var myData = {
      "data": {
        "description": "Share and rank tips for eating healthily on the cheaps!", 
        "name": "Eating Healthy & Cheap", 
        "videoSubmissionAllowed": false
      }
    };

    $.ajax({

        url: 'https://www.googleapis.com/moderator/v1/series?key='+key,
        type: 'POST',
        callback: '?',
        data: myData,
        datatype: 'application/json',
        success: function() { alert("Success"); },
        error: function() { alert('Failed!'); },
        beforeSend: setHeader

    });
}

function setHeader(xhr) {

  xhr.setRequestHeader('Authorization', token);
}

function doLogin(){ 
    if (token == ''){
       token = google.accounts.user.login(scope);
    }else{
       alert('already logged');
    }
}


function doCheck(){             
    token = google.accounts.user.checkLogin(scope);
    return token;
}
</script>
...
...
<div data-role="content">
    <input type="button" value="Login" onclick="doLogin();">
    <input type="button" value="Get data" onclick="getModerator();">
    <input type="button" value="Create" onclick="create();">
</div><!-- /content -->
rubdottocom
źródło
1
czy mógłbyś umieścić swój kod nieco dokładniej? Nie mogłem uruchomić twojego kodu.
Hosein Aqajani,

Odpowiedzi:

249

Rozwiązałem błąd Access-Control-Allow-Origin modyfikując parametr dataType na dataType: 'jsonp' i dodając crossDomain: true

$.ajax({

    url: 'https://www.googleapis.com/moderator/v1/series?key='+key,
    data: myData,
    type: 'GET',
    crossDomain: true,
    dataType: 'jsonp',
    success: function() { alert("Success"); },
    error: function() { alert('Failed!'); },
    beforeSend: setHeader
});
rubdottocom
źródło
20
Myślę, że nie crossDomain:truejest to wymagane. Rozumiem, że jest to konieczne tylko wtedy, gdy wykonujesz żądanie we własnej domenie, ale chcesz, aby jQuery traktował je jak żądanie międzydomenowe.
Alex W
7
crossDomainnie jest potrzebne. jest to zwykłe jsonpżądanie przeznaczone do komunikacji między domenami.
hitautodestruct
50
Otrzymuję ten sam błąd, ale chcę opublikować żądanie. jsonp nie obsługuje POST. Jak mogę to rozwiązać?
iamjustcoder
7
Zmieniłeś także metodę z POST na GET
Dave Baghdanov
5
@rubdottocom co jeśli adres URL zwróci odpowiedź XML zamiast json ...?
Biuro programistów,
43

Miałem dokładnie ten sam problem i nie był to problem międzydomenowy, ale ta sama domena. Właśnie dodałem tę linię do pliku php, który obsługiwał żądanie ajax.

<?php header('Access-Control-Allow-Origin: *'); ?>

Zadziałało jak urok. Dzięki plakatowi

Muhammad Tanweer
źródło
29
To jest bardzo niebezpieczne. Jeśli komuś uda się wstrzyknąć javascript na Twoją stronę, może z łatwością „zadzwonić do domu” z wszelkimi informacjami, które poda użytkownik.
dclowd9901
@ dclowd9901: „Niebezpieczne” jest względne w zależności od celu użycia i zastosowanych środków, między innymi w celu ustawienia nagłówka Access-Control-Allow-Origin jako anonimowego .
nyedidikeke
6

Jeśli masz ten błąd podczas próby wykorzystania usługi, której nie możesz dodać nagłówka Access-Control-Allow-Origin *w tej aplikacji, ale możesz umieścić przed serwerem odwrotne proxy, błędu można uniknąć, przepisując nagłówek.

Zakładając, że aplikacja działa na porcie 8080 (domena publiczna www.mydomain.com ) i umieścisz odwrotne proxy na tym samym hoście na porcie 80, to jest konfiguracja dla zwrotnego proxy Nginx :

server {
    listen      80;
    server_name www.mydomain.com;
    access_log  /var/log/nginx/www.mydomain.com.access.log;
    error_log   /var/log/nginx/www.mydomain.com.error.log;

    location / {
        proxy_pass   http://127.0.0.1:8080;
        add_header   Access-Control-Allow-Origin *;
    }   
}
Mariano Ruiz
źródło
2
Jak wspomniano powyżej, użycie znaku „*” jest bardzo niebezpieczne.
Adaddinsane
5
Tak, ale w zależności od tego, co ujawniasz. Jeśli publikujesz publiczne API bez autoryzacji, tak właśnie jest (mój przypadek). Jeśli nie, ty powinien być użyty somethig tak: Access-Control-Allow-Origin: http://example.com.
Mariano Ruiz
2
kiedy testuję interfejs API przez listonosza i ajax. ale prośba listonosza się powiodła. ale w AJAX zwraca false.
Araf
@Araf postman i inne aplikacje nie wyzwalają zabezpieczeń CORS wbudowanych w przeglądarki.
SenseiHitokiri,
6

Tak, w momencie, gdy jQuery widzi, że adres URL należy do innej domeny, zakłada, że ​​połączenie to jest połączeniem międzydomenowym, dlatego crossdomain:truenie jest tutaj wymagane.

Należy również pamiętać, że nie można wykonać połączenia synchronicznego z, $.ajaxjeśli adres URL należy do innej domeny (między domenami) lub jeśli używasz formatu JSONP. Dozwolone są tylko połączenia asynchroniczne.

Uwaga: możesz zadzwonić do usługi synchronicznie, jeśli określisz to async:falsew swoim żądaniu.

Vivek Jain
źródło
0

W moim przypadku problem powoduje nazwa domeny podrzędnej. Oto szczegóły

Użyłem app_development.something.com, tutaj _subdomena podkreślenia ( ) tworzy błąd CORS. Po zmianie app_developmentna app-developmentto działa dobrze.

Zero
źródło
0

Jest mały hack z php. Działa nie tylko z Google, ale z każdą witryną, której nie kontrolujesz i której nie możesz dodać Access-Control-Allow-Origin *

Musimy stworzyć plik PHP (np. GetContentFromUrl.php ) na naszym serwerze WWW i zrobić małą sztuczkę.

PHP

<?php

$ext_url = $_POST['ext_url'];

echo file_get_contents($ext_url);

?>

JS

$.ajax({
    method: 'POST',
    url: 'getContentFromUrl.php', // link to your PHP file
    data: {
        // url where our server will send request which can't be done by AJAX
        'ext_url': '/programming/6114436/access-control-allow-origin-error-sending-a-jquery-post-to-google-apis'
    },
    success: function(data) {
        // we can find any data on external url, cause we've got all page
        var $h1 = $(data).find('h1').html();

        $('h1').val($h1);
    },
    error:function() {
        console.log('Error');
    }
});

Jak to działa:

  1. Twoja przeglądarka przy pomocy JS wyśle ​​zapytanie do Twojego serwera
  2. Twój serwer wyśle ​​żądanie do dowolnego innego serwera i otrzyma odpowiedź z innego serwera (dowolnej witryny)
  3. Twój serwer wyśle ​​tę odpowiedź do twojego JS

I możemy tworzyć zdarzenia po kliknięciu, umieścić to zdarzenie na jakimś przycisku. Mam nadzieję, że to pomoże!

dfox
źródło