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 -->

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
});

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


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 *;
    }   
}

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.


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.


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!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.