Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Ta sama sesja na roznych domenach
Forum PHP.pl > Forum > PHP
Seth
Mam taki ciekawy problem do rozgryzienia ktorym chcialem sie z Wami podzielic.

Calosc rozchodzi sie o uwierzytelnianie uzytkownika na roznych domenach.
Zalozmy, ze mamy serwis na domenie example.com
Na nim dokonuje sie autoryzacja uzytkownika.
Uzytkownik po kliknieciu na link, kierujacy go do innej domeny (example.pl) ma byc juz zalogowany z tymi samym loginem i uprawnieniami co na bazowej domenie.

Oczywiscie nie da sie ustawic ciasteczka sesyjnego dla kilku domen, wiec ten spsob odpada.

Serwisy nie posiadaja zcenralizowanego mechanizmu przechowywania sesji, a wiec nie mozna tez od tak przekazac ID sesji np po przez URL.



Resaumujac wyglada to tak: loguje sie na serwisie excample.com, przechodze na serwis example.pl i jestem zalogowany z tym samym loginem co na example.com.


Moim pomyslem na rozwaizanie tego problemu jest nastepujacy:

Serwis example.com, w momencie gdy uzytkownik sie zaloguje, serwuje mu strone - strona ta zawiera odwolanie do skryptu PHP generujacego przezroczysty obrazek 1x1 px.
Serwis ten przekazuje w parametrze np. <img src="http://example.pl/activate.php?sesid=123" ... /> zmienna sesid.
Okresla ona ID sesji na serwerze example.com
W momencie kiedy zostaje wywolany skrypt active.php (ktory jest tak naprawde obrazkiem) pobierana jest zmienna sesid.
Nastepnie skrypt uruchamia sesje (session_start()).
Pozniej sprawdza czy istnieje zmienna np. $_SESSION['auth'] ktora ma wartosc true - po to aby sprawdzic czy przypadkiem juz wczesniej nie zostala aktywowana sesja (czy wczesniej nie bylo wywolania tego skryptu).
Jezeli nie ma takiej zmiennej, skrypt odsyla wartosc zmiennej sesid do serwera example.com w celu zweryfikowania czy sesja jest autentyczna.
Tutaj mozna uzyc albo WebServices albo po prostu wywolac adres http://example.com/is_valid?sesid=<i tutaj wartosc zmiennej sessid przekazana do skryptu activate.php> - w odpowiedzi dostali bysmy np '1'
Jezeli jest ustawia zmienna $_SESSION['auth'] na true.

Dzieki temu sesja moze byc niejako przekazywana miedzy domenami.


Co o tym sadzicie, jakie sa Wasze pomysly?


P.S.
Jezeli cos jest neizrozumiale prosze pytac winksmiley.jpg
b_chmura
ciemniak jestem ale nie lepiej byłoby zastosować cURL? przy logowaniu na example.com cURL z tymi samymi danymi loguje nas na example.pl
Seth
Tez o tym myslalem, ale musze zalozyc pesymysityczna sytuacje, ze serwis example.com poza udostepnieniem weryfikacji IDka sesji wiele wiecej nie zaoferuje. Stad takie kombinowanie :/



Edit winksmiley.jpg przypomnialo mi sie czemu cURL nie bedzie tutaj rozwiazaniem - on nie zapiszze ciastka sesjnego w przegladarce. A tylko to pozwoli na wesjcie na strone exxample.pl bez potrzeby logowania.
heaven
Może nie do konca rozumiem ale wydaje mi sie ze cURL'em mozesz to zrobic. logujac sie w sewisie example.pl skrypt wysyla cURL'a do example.com z danymi do logowania - odczytuje czy sie powiodo i jesli tak ustawia u siebie (example.pl) $_SESSION['auth'] na true i to chyba wystarczy??
Seth
cURL dziala jak by bylo przegladarka. Dlatego nawet gdy wyslemy rzadanie do example.com o zalogowanie sie, to ciasteczko sesyjne zostanie ustawione tylko dla sesji cURL. Gdybysmy weszli na strone example.pl to w przegladarce nie bedziemy mieli ciasteczka z sesja.

Tu wlasnie jest ten problem. Dzisaij siedzialem jeszcze troche nad tym i doczytalem sie, ze takie jak moje rozwiazanie nazwya sie 3rd party cookie.
Jest stosowane przez serwisy trackujace uzytkownikow i dostarczajace im reklam. Chociaz czesciej uzywaja iframewow ale zasada jest ta sama smile.gif
Niedoczytalem sie jeszcze szczegolow, ale OpenID dziala w podobny spsob - jesli chodzi o autoryzacje sesji (przeslanie IDka sesji i zweryfikowanie czy jest on poprawny).
Kocurro
Seth z tego co czytam: http://en.wikipedia.org/wiki/HTTP_cookie#P...d-party_cookies wychodzi na to, że i tak trzeba użyć sztuczki z 1x1trans'em winksmiley.jpg Albo iframem albo czymkolwiek innym byle tylko wygenerowało odpowiedni request.

A myślałeś nad Ajaxem ? bo ja właśnie będę kombinował rozwiązanie tego problemu za pomocą ajaxa. Próbowałem już chain'em forwardów ale nie idzie to dobrze.

pozdr.
Seth
@Kocurro: apropo 1x1 px to wlasnie tego uzyje - w polaczeniu z weryfikacja IDka sesji przekazanego do tego "obrazka" po przez Web Services (wysylajac rzadanie do example.com).

Co do AJAXa to nie wywolasz skrypt z innej domeny niz aktywna - przegladarka tego zabrania :/




Co do tego 3rd party cookie to przygotowalem maly przyklad:

1) strona ktora otrzyma informacje o tym, ze uzytkownik jest zalogowany na innej domenie:
http://www.webarchitect.net.pl/lab/04/3rd.php

Po wejsciu widac, ze sesja nie jest uruchomiona.


2) Strona na ktorej logujemy sie i za pomoca obrazka ustawiamy sesje na innej domenie:
http://www.webarchitect.pl/lab/04/3rd_logged.php


3) Teraz wracamy na strone:
http://www.webarchitect.net.pl/lab/04/3rd.php

I mamy informacje, ze sesja zostala utworzona smile.gif
krowal
A co myślicie o zastosowaniu własnego systemu sesji opartego na bazie danych (tej samej dla kilku domen) oczywiście musiałaby mieć możliwość podpięcia się z zewnątrz a nie tylko z localhosta. Wtedy jednorazowe przekazywanie id sesji w url podczas przechodzenia między różnymi domenami miałoby sens. Id sesji byłoby przekazywane raz a potem będąc na domenie tworzymy dla niej ciastko w której przechowujemy to id. Za przechowywanie danych sesyjnych odpowiada klasa napisana specjalnie do obsługi całej sesji użytkownika. Pobiera dane, zapisuje itp (np w formie zserializowanej).
Kocurro
Seth: No faktycznie Ajax odpada, Java pewnie także. Więc pozostaje tylko iframe lub obrazek. Iframe'ów nie lubię bo brzydko się zachowują jak są błędy więc użyję obrazka. Przy okazji wykorzystam onError i onLoad (czy jak to się zwie winksmiley.jpg ) - będzie można odpowiednio zareagować jak będzie błąd. Może zrobię tak, że jak błąd wyskoczy to header Location przepuszcze ... jeszcze zobaczę.

Aż dziw bierze, że do dziś dnia nie opracowali jakiegoś prostego sposobu by problem rozwiąząć. Np.

Na serwisie X wysyłam coś z informacją, że do tego cosia można się odwoływać z domen Z, Y, W. I potem pod tymi domenami spokojnie cosia odczytuję i voila. Nie jest to trudne do zaimplementowania a jakże pomocne by było ...

Krowal: Zakładam, że te sesje są w bazie winksmiley.jpg Na takie "machlojki" najlepiej napisać uniwersalną klasę, która za nas zrobi co należy winksmiley.jpg
Seth
Dlatego wlasnie powstaly inicjatywy typu OpenID, .NET Passport itp. winksmiley.jpg

.NET Passport jest zamkniety, ale OpenID juz nie - chociaz sadze, ze dla malych projektow, zaimplementowanie go bylo by wg. mnie strzelaniem z armaty do wrobla.



P.S.
moze komus sie to przyda wiec, podrzucam kod tych trzech skryptow.
Nie jest to nic wielkiego ale przynajmniej rozjasni sposob dzialania.


3rd_logged.php (rozszerzenie .php dalem tutaj z rozpedu winksmiley.jpg)
  1. <img src="http://www.webarchitect.net.pl/lab/04/3rd_set.php" /><br />
  2. Ustawilem sesje na webarchitect.net.pl



3rd_set.php:
  1. <?php
  2.  
  3. $_SESSION['test'] = 'ok';
  4.  
  5. header('Content-type: image/gif');
  6. echo file_get_contents('jakis_obrazek.gif');
  7. ?>


3rd.php:
  1. <?php
  2.  
  3. echo 'Sesja zostala utworzona? ' . ($_SESSION['test'] == 'ok' ? 'tak' : 'nie');
  4. ?>
Kocurro
Nie da się ukryć.

Z tego co tam czytam to ja będę podobny mechanizm jak OpenID wprowadzał ... na potrzeby swojej i kilku innych firm oraz serwisów tworzonych ... tzn. to jest w planach a co z tego wyjdzie - "time will show" winksmiley.jpg

A myślałeś by stworzyć jakąś uniwersalną klasę, którą po prostu byś używał w dowolnych swoich serwisach itp., łatwo konfigurując go ?

Bo ja właśnie o tym myślę:) Potrzebne mi coś co zrobię raz a potem nie będę do tego więcej zaglądał biggrin.gif

Edit:

Jak skończę klasę to się nią podzielę biggrin.gif
Seth
Narazie mialem sprawdzic jak mozna to rozwiazac i przygotowac maly proof of concept, wiec sadze, ze juz inni beda sie zajmowac przygotwaniem odpowiednich klas winksmiley.jpg
spamcop
Ja mam inna dzialajaca :] koncepcje. Potrzebna jest jednak baza np MySQl do ktorej maja dostep wszystkie serwery,
pomiedzy ktorymi chcemy przekazywac sesje. 
Tutaj opisze ogolna koncepcje wersji najprostszej.
Zakladamy tabele w mysqlu np jak ponizej.
Bedziemy przekazywac tylko username, ale mozna oczywiscie dowolne
zmienne sesji w formie zakodowanej session_encode lub jawnej

CREATE TABLE `session_transfer` (
`id` int(10) unsigned NOT NULL auto_increment,
`pid` varchar(64) NOT NULL,
`username` varchar(64) NOT NULL,
`expiration` varchar(16) NOT NULL,
`target_host` varchar(254) NOT NULL,
PRIMARY KEY (`id`)
)

pid - losowy id sesji
username - przekazywany parametr
expiracja - czas do ktorego nalezy wykorzystac pida
host_fw - nazwa hosta docelowego

Na kazdym serwerze funkcjonuja 2 includy:
session_send.php ktory wysyla usera na innego hosta
session_receive.php ktory przyjmuje usera z innego hosta

W momencie przerzucania sesji (klikniecie w button), session_send.php tworzy pida
i wpisuje pida i reszte danych do bazy ustalajac czas expiracji np na 2-3s,
wpisuje tez hosta docelowego i na potrzeby usera tworzy URL z pidem
i domeną przyporzadkowana do hosta docelowego. Przekierowuje za pomoca header()
User klikajac na buttonie przenosi pida na hosta docelowego

Na hoscie docelowym session_receive.php przyjmuje pida i czyta z bazy
wszystkie potrzebne dane odpalajac sesje, sprawdza przy tym czy czas transferu
nie zostal przekroczony (expiracja) oraz czy host docelowy jest ten sam jaki jest
w target_host. Jesli wszystko jest ok podstawia na nowym hoscie odpowiednie
dane do sesji i mozna sie bawic jako zalogowany user na zupelnie innej domenie.
jesli pid sie nie zgadza, albo np wyekspirowal mozna ustawic powrot
na hosta macierzystego.

Mechanizm ogolnie prosty jak budowa cepa. Pisanie do tego jakis skomplikowanych klas to IMO przerost formy nad trescia. wystarcza dwa includy po parenascie linii kodu z zapytaniami do bazy INSERT i SELECT

Jesli cos niejasne prosze pytac. Milej zabawy.

--
(spamcop[at]interia.pl)
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.