Pochodzenie nie jest dozwolone przez Access-Control-Allow-Origin


337

Robię Ajax.requestna zdalnym serwerze PHP w aplikacji Sencha Touch 2 ( zawartej w PhoneGap ).

Odpowiedź serwera jest następująca:

XMLHttpRequest nie może załadować http://nqatalog.negroesquisso.pt/login.php . Pochodzenie http://localhost:8888nie jest dozwolone przez Access-Control-Allow-Origin.

Jak mogę rozwiązać ten problem?


19
podczas korzystania z jQuery, ustawienie dataType: 'jsonp',robi
załatwienie

11
tak przy okazji, to nie jest odpowiedź serwera. Mówiąc ściślej, ten błąd jest wydawany po stronie klienta.
matteo

2
Sztuczka jsonp prawdopodobnie już nie działa, fyi: stackoverflow.com/questions/12216208/...
Drawww

7
Uwaga, ponieważ właśnie zmarnowałem pół dnia na ściganie tego błędu - jeśli skrypt po stronie serwera zawiedzie z wewnętrznym błędem serwera, przeglądarka może zinterpretować go tak, jakby żądanie nie było dozwolone z powodu Access-Control-Allow-Origini zgłosić to jako błąd.
troelskn

1
@troelskn Właśnie uratowałeś mi życie. Szukałem błędu CORS od 3 dni i był to po prostu mały problem z konfiguracją wiosenną, powodujący 500, który rozwiązałem w 5 minut po przeczytaniu twojego komentarza i faktycznie go szukałem. Dziękuję Ci!
Alexis Dufrenoy

Odpowiedzi:


378

Niedawno napisałem artykuł na ten temat, Cross Domain AJAX .

Najłatwiejszym sposobem poradzenia sobie z tym, jeśli masz kontrolę nad serwerem odpowiadającym, jest dodanie nagłówka odpowiedzi dla:

Access-Control-Allow-Origin: *

Umożliwi to Ajax między domenami . W PHP będziesz chciał zmodyfikować odpowiedź w następujący sposób:

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

Możesz po prostu umieścić to Header set Access-Control-Allow-Origin *ustawienie w Apache konfiguracji lub pliku htaccess.

Należy zauważyć, że to skutecznie wyłącza ochronę CORS, co bardzo prawdopodobne naraża użytkowników na atak . Jeśli nie wiesz, że konkretnie potrzebujesz użyć symbolu wieloznacznego, nie powinieneś go używać, a zamiast tego powinieneś dodać białą listę do swojej konkretnej domeny:

<?php header('Access-Control-Allow-Origin: http://example.com') ?>

4
Skontaktuję się z dostawcą mojego serwera. Dzięki
Ricardo,

8
Czy są z tym jakieś obawy związane z bezpieczeństwem? Ta odpowiedź mówi na przykład: „JavaScript jest ograniczony przez„ zasady tego samego pochodzenia ”ze względów bezpieczeństwa, na przykład złośliwy skrypt nie może skontaktować się ze zdalnym serwerem i wysłać poufnych danych z Twojej witryny”.
JohnK

4
Wspaniale, właśnie wstawiłem to do pliku serwera node.js: response.writeHead (200, {„Content-Type”: contentType, „Access-Control-Allow-Origin”: „*”}); I zadziałało. Dzięki!
vbullinger

25
JohnK, tak, symbol wieloznaczny pozwoli dowolnej domenie na wysyłanie żądań do twojego hosta. Zalecam zastąpienie gwiazdki określoną domeną, na której będą uruchamiane skrypty.
Nick

7
Interesujące jest to, że uważasz, że symbol wieloznaczny nie powinien nawet być sugerowany @jfrej. Wszystko zależy od twojego celu. Na przykład użyliśmy symbolu wieloznacznego (i opublikowaliśmy tę odpowiedź), ponieważ budowaliśmy wbudowany widget dla dowolnej witryny.
Matt Mombrea

63

Jeśli nie masz kontroli nad serwerem, możesz po prostu dodać ten argument do programu uruchamiającego Chrome:--disable-web-security .

Pamiętaj, że nie użyłbym tego do normalnego „surfowania po Internecie”. W celach informacyjnych zobacz ten post: Wyłącz tę samą zasadę pochodzenia w Chrome .

Jeśli użyjesz Phonegap do zbudowania aplikacji i załadowania jej na urządzenie, nie będzie to problemem.


Dzięki. Ale moja aplikacja działa na urządzeniach mobilnych, nie mogę przekazywać argumentów do opakowania WebView.
Ricardo

Czy najpierw nie testujesz aplikacji w przeglądarce? Jak debugujesz?
Travis Webb,

Tak, debuguję w przeglądarce Chrome, ale aplikacja nie działa na Chrome. Będzie to na widoku sieci telefonicznej, którego nie mogę kontrolować.
Ricardo

4
przeczytaj odpowiedź: możesz po prostu dodać ten argument do programu uruchamiającego Chrome . W Chrome nie ma takiego ustawienia
Travis Webb

2
Oczywiście to niepewne. OP prosi o obejście środków bezpieczeństwa.
Travis Webb,

42

Jeśli używasz Apache, po prostu dodaj:

<ifModule mod_headers.c>
    Header set Access-Control-Allow-Origin: *
</ifModule>

w twojej konfiguracji. Spowoduje to, że wszystkie odpowiedzi z twojego serwera będą dostępne z dowolnej innej witryny w Internecie. Jeśli zamierzasz zezwolić, aby usługi na Twoim hoście były używane tylko przez określony serwer, możesz zastąpić *adresem URL serwera źródłowego:

Header set Access-Control-Allow-Origin: http://my.origin.host

3
I nie zapomnij załadować modułu: nagłówki a2enmod
Walery Strauch,

jak załadować moduł: nagłówki a2enmod?
Ayesha,

18

Jeśli masz aplikację ASP.NET / ASP.NET MVC , możesz dołączyć ten nagłówek za pomocą pliku Web.config:

<system.webServer>
  ...

    <httpProtocol>
        <customHeaders>
            <!-- Enable Cross Domain AJAX calls -->
            <remove name="Access-Control-Allow-Origin" />
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

2
.NET MVC Ludzie, PATRZ tutaj! Zamierzam napisać rozwiązanie i wskazać tę odpowiedź na moim blogu, aby ludzie mogli łatwiej ją znaleźć. Nic gorszego niż próba pokonania przeszkody .NET / MVC i znalezienia niczego poza rozwiązaniami PHP / jQuery. Dzięki @ Caio-Proiete
ottoflux

1
Dlaczego to nie działa dla mnie? Używam Chrome i próbuję uzyskać dostęp do strony finansów Yahoo z mojego lokalnego hosta.
newman

1
dzięki, że zadziałało dla mnie. Dodałem w projekcie kodu po stronie serwera (web.config).
ethem

15

To było pierwsze pytanie / odpowiedź, które pojawiło się dla mnie, gdy próbowałem rozwiązać ten sam problem za pomocą ASP.NET MVC jako źródła moich danych. Zdaję sobie sprawę, że to nie rozwiązuje PHP pytania , ale jest wystarczająco powiązane, aby być cennym.

Używam ASP.NET MVC. Blogu z Gregiem Brant pracował dla mnie. Ostatecznie tworzysz atrybut,[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")] który możesz dodawać do akcji kontrolera.

Na przykład:

public class HttpHeaderAttribute : ActionFilterAttribute
{
    public string Name { get; set; }
    public string Value { get; set; }
    public HttpHeaderAttribute(string name, string value)
    {
        Name = name;
        Value = value;
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.AppendHeader(Name, Value);
        base.OnResultExecuted(filterContext);
    }
}

A następnie używając go z:

[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
    return Json( "Some public result" );
}

1
WebApi 2 ma to teraz wbudowane. asp.net/web-api/overview/security/…
Matt

10

Ponieważ Matt Mombrea jest poprawny po stronie serwera, możesz napotkać inny problem, którym jest odrzucenie białej listy.

Musisz skonfigurować phonegap.plist. (Używam starej wersji phonegap)

W przypadku Kordowa mogą wystąpić pewne zmiany w nazwie i katalogu. Ale kroki powinny być w większości takie same.

Najpierw wybierz Pliki pomocnicze> PhoneGap.plist

wprowadź opis zdjęcia tutaj

następnie w „ExternalHosts”

Dodaj wpis o wartości „ http://nqatalog.negroesquisso.pt ” Używam * tylko do celów debugowania.

wprowadź opis zdjęcia tutaj


8

Może to być przydatne dla każdego, kto potrzebuje wyjątku zarówno dla wersji strony odsyłającej „www”, jak i „innej niż www”:

 $referrer = $_SERVER['HTTP_REFERER'];
 $parts = parse_url($referrer);
 $domain = $parts['host'];

 if($domain == 'google.com')
 {
         header('Access-Control-Allow-Origin: http://google.com');
 }
 else if($domain == 'www.google.com')
 {
         header('Access-Control-Allow-Origin: http://www.google.com');
 }

Wskazał mi właściwy kierunek w rozwiązaniu błędu ACAO za pomocą lazuru. Podczas gdy dodałem dozwoloną nazwę hosta googledrive. Używany adres URL musi być googledrive NIE googledrive
Kildareflare

7

Dam ci proste rozwiązanie tego problemu. W moim przypadku nie mam dostępu do serwera. W takim przypadku możesz zmienić zasady bezpieczeństwa w przeglądarce Google Chrome, aby zezwolić na Access-Control-Allow-Origin. To jest bardzo proste:

  1. Utwórz skrót przeglądarki Chrome
  2. Kliknij prawym przyciskiem myszy ikonę skrótu -> Właściwości -> Skrót -> Cel

Proste wklejanie "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.

Lokalizacja może się różnić. Teraz otwórz Chrome, klikając ten skrót.



6

Jeśli piszesz Chrome Extension i dostać ten błąd, a następnie upewnij się, że zostały dodane bazowy URL API do swojej manifest.json„s uprawnienia blok , na przykład:

"permissions": [
    "https://itunes.apple.com/"
]


6

jeśli korzystasz z Apache, po prostu dodaj plik .htaccess do katalogu z tą zawartością:

Header set Access-Control-Allow-Origin: *

Header set Access-Control-Allow-Headers: content-type

Header set Access-Control-Allow-Methods: *

5

W Ruby on Rails możesz zrobić w kontrolerze:

headers['Access-Control-Allow-Origin'] = '*'

w jakim kontrolerze umieścisz to, jeśli jest to wywołanie ajax? Czy mogę zobaczyć więcej kontekstu kodu?
rigdonmr

5

Możesz sprawić, aby działał bez modyfikowania serwera, tworząc broswer zawierający nagłówek Access-Control-Allow-Origin: * w odpowiedziach OPCJI HTTP.

W Chrome użyj tego rozszerzenia . Jeśli korzystasz z Mozilli, sprawdź tę odpowiedź .


5

Jeśli otrzymujesz to w Angular.js, upewnij się, że nie masz numeru portu:

var Project = $resource(
    'http://localhost\\:5648/api/...', {'a':'b'}, {
        update: { method: 'PUT' }
    }
);

Zobacz tutaj, aby uzyskać więcej informacji na ten temat.


4

Mamy również ten sam problem z aplikacją phonegap testowaną w chromie. Jedna maszyna z systemem Windows, której używamy codziennie poniżej pliku wsadowego przed otwarciem Chrome. Pamiętaj, że przed uruchomieniem tego musisz wyczyścić wszystkie wystąpienia chrome z menedżera zadań lub możesz wybrać chrome, aby nie działał w tle.

SERIA: (użyj cmd)

cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security


0

Po otrzymaniu prośby możesz

var origin = (req.headers.origin || "*");

niż kiedy musisz odpowiedzieć, idź z czymś takim:

res.writeHead(
    206,
    {
        'Access-Control-Allow-Credentials': true,
        'Access-Control-Allow-Origin': origin,
    }
);
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.