Sposoby obchodzenia polityki tego samego pochodzenia

150

Ta sama polityka pochodzenia

Chciałem stworzyć wiki społeczności dotyczące zasad HTML / JS tego samego pochodzenia, aby pomóc każdemu, kto szuka tego tematu. Jest to jeden z najczęściej wyszukiwanych tematów w SO i nie ma dla niego skonsolidowanej wiki, więc zaczynam :)

Ta sama zasada pochodzenia zapobiega pobieraniu lub ustawianiu właściwości dokumentu z innego źródła przez dokument lub skrypt załadowany z jednego źródła. Ta polityka sięga aż do Netscape Navigator 2.0.

Jakie są Twoje ulubione sposoby obchodzenia zasad dotyczących tego samego pochodzenia?

Prosimy o rozwiązywanie przykładów, a najlepiej także łączenie źródeł.

David Titarenco
źródło
4
fajny pomysł .. Jednak powinieneś umieścić swoje przykłady w odpowiedziach; w obecnym stanie sprawiają, że pytanie jest raczej nieporęczne
Shog9
1
Należy również dodać listę konsekwencji dla bezpieczeństwa dla każdego podejścia. JSONP jest wysoce niebezpieczny dla danych prywatnych.
Erlend
Dlaczego zamknięcie? To (wiki) pytanie było bardzo przydatne przez ostatnie 2 lata. Ponadto wiele odpowiedzi jest popartych referencjami. Wyjaśnienie byłoby mile widziane, ponieważ not constructivetag wydaje się kompletnie bezsensowny. Zagłosowano na ponowne otwarcie.
David Titarenco

Odpowiedzi:

84

document.domainmetoda

  • Typ metody: iframe .

Zauważ, że jest to metoda iframe, która ustawia wartość document.domain na przyrostek bieżącej domeny. Jeśli tak się stanie, krótsza domena jest używana do kolejnych kontroli pochodzenia. Na przykład załóżmy, że skrypt w dokumencie http://store.company.com/dir/other.htmlwykonuje następującą instrukcję:

document.domain = "company.com";

Po wykonaniu tej instrukcji strona przeszłaby sprawdzenie pochodzenia http://company.com/dir/page.html. Jednak tego samego rozumowania, company.com nie może ustawić document.domain się othercompany.com.

Dzięki tej metodzie możliwe byłoby wykonanie javascript z elementu iframe pochodzącego z subdomeny na stronie pochodzącej z domeny głównej. Ta metoda nie jest odpowiednia dla zasobów międzydomenowych, ponieważ przeglądarki takie jak Firefox nie pozwalają na zmianę document.domaindomeny na całkowicie obcą.

Źródło: https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript

Metoda udostępniania zasobów między źródłami

  • Typ metody: AJAX .

Współdzielenie zasobów między źródłami (CORS) to robocza wersja robocza W3C, która definiuje sposób komunikacji przeglądarki i serwera podczas uzyskiwania dostępu do źródeł z różnych źródeł. Podstawową ideą CORS jest użycie niestandardowych nagłówków HTTP, aby umożliwić zarówno przeglądarce, jak i serwerowi wzajemne poznanie się, aby określić, czy żądanie lub odpowiedź powinny się powieść, czy nie.

W przypadku prostego żądania, które używa niestandardowych nagłówków GETlub POSTbez nich i którego treść jest text/plain, żądanie jest wysyłane z dodatkowym nagłówkiem o nazwie Origin. Nagłówek Origin zawiera pochodzenie (protokół, nazwę domeny i port) strony żądającej, dzięki czemu serwer może łatwo określić, czy powinien dostarczyć odpowiedź. Przykładowy Originnagłówek może wyglądać następująco:

Origin: http://www.stackoverflow.com

Jeśli serwer zdecyduje, że żądanie powinno być dozwolone, wysyła Access-Control-Allow-Originnagłówek powracający do tego samego źródła, które zostało wysłane, lub *jeśli jest to zasób publiczny. Na przykład:

Access-Control-Allow-Origin: http://www.stackoverflow.com

Jeśli brakuje tego nagłówka lub źródła nie są zgodne, przeglądarka odrzuca żądanie. Jeśli wszystko jest w porządku, przeglądarka przetwarza żądanie. Należy pamiętać, że ani żądania, ani odpowiedzi nie zawierają informacji o plikach cookie.

Zespół Mozilli sugeruje w swoim poście na temat CORS , aby sprawdzić istnienie withCredentials właściwości, aby określić, czy przeglądarka obsługuje CORS przez XHR. Następnie możesz powiązać istnienie XDomainRequestobiektu, aby objąć wszystkie przeglądarki:

function createCORSRequest(method, url){
    var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){
        xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){
        xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {
        xhr = null;
    }
    return xhr;
}

var request = createCORSRequest("get", "http://www.stackoverflow.com/");
if (request){
    request.onload = function() {
        // ...
    };
    request.onreadystatechange = handler;
    request.send();
}

Zwróć uwagę, że aby metoda CORS działała, musisz mieć dostęp do dowolnego typu mechaniki nagłówka serwera i nie możesz po prostu uzyskać dostępu do zasobów stron trzecich.

Źródło: http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/

window.postMessagemetoda

  • Typ metody: iframe .

window.postMessage, po wywołaniu, powoduje wywołanie a MessageEventw oknie docelowym, gdy jakikolwiek oczekujący skrypt, który musi zostać wykonany, zakończy się (np. pozostałe programy obsługi zdarzeń, jeśli window.postMessagejest wywoływane z modułu obsługi zdarzeń, wcześniej ustawione oczekujące limity czasu itp.). MessageEventMa wiadomość typu, datanieruchomości, który jest ustawiony na wartość ciągu pierwszego argumentu dostarczonych window.postMessageAn originnieruchomość odpowiadającą pochodzenia głównego dokumentu w oknie wywołującego window.postMessagew momencie window.postMessagenazwano oraz sourcemienia, które jest okno z który window.postMessagejest nazywany.

Aby użyć window.postMessage, należy dołączyć detektor zdarzeń:

    // Internet Explorer
    window.attachEvent('onmessage',receiveMessage);

    // Opera/Mozilla/Webkit
    window.addEventListener("message", receiveMessage, false);

A receiveMessagefunkcja musi zostać uznana:

function receiveMessage(event)
{
    // do something with event.data;
}

Element iframe poza witryną musi również prawidłowo wysyłać zdarzenia za pośrednictwem postMessage:

<script>window.parent.postMessage('foo','*')</script>

Każde okno może uzyskać dostęp do tej metody w dowolnym innym oknie, w dowolnym momencie, niezależnie od lokalizacji dokumentu w oknie, aby wysłać do niego wiadomość. W związku z tym każdy detektor zdarzeń używany do odbierania wiadomości musi najpierw sprawdzić tożsamość nadawcy wiadomości, używając pochodzenia i prawdopodobnie właściwości źródła. Nie można tego bagatelizować: brak sprawdzenia origini prawdopodobnie sourcewłaściwości umożliwia ataki typu cross-site scripting.

Źródło: https://developer.mozilla.org/en/DOM/window.postMessage

David Titarenco
źródło
Mam nadzieję, że nie jestem za późno, aby uzyskać odpowiedź: tylko pytanie brzmi, czy localhost ZAWSZE jest wyjątkiem? czy to zawsze jest niedozwolone? czy powinienem przerwać testowanie za pośrednictwem mojego hosta lokalnego?
Ayyash
1
Nie wiem dlaczego, ale kiedy ustawiam: Access-Control-Allow-Origin: http://www.stackoverflow.com/zamiast: Access-Control-Allow-Origin: http://www.stackoverflow.com(ukośnik na końcu adresu URL), nie działa w Safari i FF, ale działa w Chrome. Oczywiście bez ukośnika działa dobrze we wszystkich przeglądarkach.
mtfk
1
Warto poinformować ludzi, że ta postMessagemetoda działa tylko w przeglądarkach, które ją obsługują, ponieważ jest to dodatek HTML5. Ta wtyczka próbuje to uwzględnić. Wspominam o tym, bo uczę się tego na własnej skórze.
IronicMuffin
41

Metoda odwrotnego proxy

  • Typ metody: Ajax

Skonfigurowanie prostego odwrotnego proxy na serwerze pozwoli przeglądarce na użycie ścieżek względnych dla żądań Ajax, podczas gdy serwer będzie działał jako proxy do dowolnej lokalizacji zdalnej.

Jeśli używasz mod_proxy w Apache, podstawową dyrektywą konfiguracyjną do skonfigurowania zwrotnego proxy jest ProxyPass. Zwykle jest używany w następujący sposób:

ProxyPass     /ajax/     http://other-domain.com/ajax/

W takim przypadku przeglądarka mogłaby zażądać /ajax/web_service.xmljako względnego adresu URL, ale serwer mógłby to obsłużyć, działając jako serwer proxy http://other-domain.com/ajax/web_service.xml.

Jedną z interesujących cech tej metody jest to, że zwrotny serwer proxy może z łatwością dystrybuować żądania do wielu zaplecza, działając w ten sposób jako moduł równoważenia obciążenia .

Daniel Vassallo
źródło
17

Używam JSONP.

Zasadniczo dodajesz

<script src="http://..../someData.js?callback=some_func"/>

na Twojej stronie.

Powinna zostać wywołana some_func (), aby otrzymać powiadomienie, że dane są w środku.

Nicolas Viennot
źródło
7
JSONP ma dwa problemy: a) Dodajesz tag skryptu do domeny docelowej. Mogą odesłać wszystko, nawet zwykły javascript (atak XSS). Więc naprawdę musisz im ufać, że nie zrobią złych rzeczy ani nie zostaną zhakowani b) Każda inna strona internetowa może dodać ten sam tag skryptu i ukraść dane, więc nigdy nie używaj JSONP do prywatnych danych.
Erlend
1
@Erlend: Każda informacja udostępniana w sieci może zostać pobrana przez każdego (chyba że wymagane jest odpowiednie uwierzytelnienie). Dokładny format prezentacji tych informacji nie poprawia tego ani nie pogarsza, nawet jeśli jest to JSONP.
T-Bull
2
@ T-Bull: Problem polega na tym, że prawidłowe uwierzytelnienie jest niemożliwe w przypadku JSONP. Użytkownik loguje się w witrynie A, a następnie przechodzi do witryny B, która ładuje dane z witryny A za pomocą tagu skryptu JSONP. Jak jest dobrze i dobrze. Następnie użytkownik zostaje nakłoniony do odwiedzenia złej strony C, która również używa tagu skryptu JSONP do ładowania danych z A. Więc ponieważ użytkownik jest uwierzytelniony za pomocą A, właściciel C może teraz ukraść dane użytkownika z A. I to nawet jeśli użytkownik użył uwierzytelniania dwuskładnikowego do uwierzytelnienia za pomocą A. Problem polega na tym, że JSONP jest wysoce niebezpieczny. A JSONP nie jest prezentacją. To niezabezpieczony transfer danych.
Erlend
1
JSONP obsługuje tylko HTTP GET.
opyate
Co oznacza plik .js -> „http: //..../someData.js.... Próbuję odczytać domenę dom z innej witryny po stronie klienta i muszę ominąć tę samą zasadę pochodzenia .
CS_2013
13

AnyOrigin nie działał dobrze z niektórymi witrynami https, więc właśnie napisałem alternatywę o otwartym kodzie źródłowym o nazwie whatorigin.org, która wydaje się dobrze działać z https.

Kod na github .

zrywak234
źródło
@DavidTitarenco - doprowadzało mnie do szału, próbując zrozumieć niektóre rzeczy, które dzieją się w brzuchu każdego pochodzenia. Na szczęście znalazłem jeden post na blogu, który pomógł, a teraz następny facet będzie miał działającą witrynę testową, jeśli kiedykolwiek będzie jej potrzebować.
ripper234
@neoascetic - naprawiono użycie ... adres URL musi być teraz zakodowany.
ripper234
12

Najnowszym sposobem na obejście zasad tego samego pochodzenia, które znalazłem, jest http://anyorigin.com/

Witryna została stworzona tak, że po prostu podajesz jej dowolny adres URL i generuje dla Ciebie kod javascript / jquery, który umożliwia pobranie html / data, niezależnie od ich pochodzenia. Innymi słowy, sprawia, że ​​dowolny adres URL lub strona internetowa jest żądaniem JSONP.

Uważam, że to całkiem przydatne :)

Oto przykładowy kod javascript z anyorigin:

$.getJSON('http://anyorigin.com/get?url=google.com&callback=?', function(data){
    $('#output').html(data.contents);
});
rk1s
źródło
Chociaż spowodowało to pewne problemy z witrynami https, więc sprawdź poniżej moją alternatywę open source: stackoverflow.com/questions/3076414/ ...
ripper234
13
Co oznacza, że: a) anyorigin będzie w stanie odczytać wszystkie Twoje dane przesłane przez tymczasowy b) anyorigin może XSS Twojej witryny, odczytać wszystkie dane w Twojej witrynie i dostarczać złośliwe oprogramowanie Twoim użytkownikom (co się stanie, jeśli którykolwiekorigin zostanie zhakowany?)
Erlend
@Erlend - rozwidlaj cokolwiekorigin i umieść na swoim serwerze. Kod jest trywialny, więc możesz go przejrzeć, aby upewnić się, że nie ma tam ukrytych exploitów.
ripper234
3

Na myśl przychodzi JSONP :

JSONP lub „JSON z dopełnieniem” to uzupełnienie podstawowego formatu danych JSON, wzorca użycia, który umożliwia stronie wysyłanie żądań i bardziej sensowne używanie formatu JSON z serwera innego niż serwer podstawowy. JSONP jest alternatywą dla nowszej metody o nazwie Cross-Origin Resource Sharing.

Sarfraz
źródło
Zobacz mój komentarz do JSONP powyżej. Nie jest to dobry wybór w przypadku danych prywatnych.
Erlend
1

Osobiście window.postMessagejest to najbardziej niezawodny sposób, jaki znalazłem dla nowoczesnych przeglądarek. Musisz trochę więcej pracy, aby upewnić się, że nie jesteś narażony na ataki XSS, ale jest to rozsądny kompromis.

Istnieje również kilka wtyczek do popularnych zestawów narzędzi Javascript, window.postMessagektóre zapewniają podobną funkcjonalność do starszych przeglądarek, wykorzystując inne metody omówione powyżej.

Justin Niessner
źródło
1

Cóż, użyłem curl w PHP, aby to obejść. Mam usługę sieciową działającą na porcie 82.

<?php

$curl = curl_init();
$timeout = 30;
$ret = "";
$url="http://localhost:82/put_val?val=".$_GET["val"];
curl_setopt ($curl, CURLOPT_URL, $url);
curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($curl, CURLOPT_MAXREDIRS, 20);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5");
curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
$text = curl_exec($curl);
echo $text;

?>

Oto javascript, który wywołuje plik PHP

function getdata(obj1, obj2) {

    var xmlhttp;

    if (window.XMLHttpRequest)
            xmlhttp=new XMLHttpRequest();
    else
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
                document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
    }
    xmlhttp.open("GET","phpURLFile.php?eqp="+obj1+"&val="+obj2,true);
    xmlhttp.send();
}

Mój HTML działa na WAMP w porcie 80. No więc, tak, ta sama polityka pochodzenia została ominięta :-)

harihb
źródło