Autor Zpráva
Pietro
Profil
Dobrý den,
řeším nyní jeden problém se kterým bych vás chtěl požádat o pomoc.
Chci vytvořit novou microsite k již existujícímu webu na vlastní doméně a pravděpodobně i na úplně jiném serveru.
Na původním webu existuje databáze uživatelů a možnost přihlášení.
Na microsite bude sekce jen pro přihlášené uživatele.

Jak docílit toho, že když se uživatel přihlásí na jednom ze serverů a přejde na druhý, nebude muset znova zadávat přihlašovací údaje? Zkrátka jak si mezi sebou bezpečně předávat informace o autentizaci?

Za jakýkoliv nápad budu vděčný.
Knight
Profil
Dodám jen takový nápad:

Uživatel se přihlásí na webu A, kde proběhne autentizace. V případě úspěchu, se na stránce po přihlášení objeví nějaký neviditelný html element stahovaný z webu B, který nastaví cookies i pro druhou doménu a druhý server. Tento element by mohl být iframe, možná by to šlo i s obrázkem, to ale nemám vyzkoušené.

V URL elementu by se muselo oznamovat, který uživaytel se přihlásil, což se může jevit jako bezpečnostní riziko, ale i to by šlo nějak řešit. Např. generováním nového názvu skriptu podle vlastního pravidla, které budou znát pouze skripty na webu A a webu B.
o_O
Profil
Pietro:
Máte možnost přihlášení k databázi A z webu B a naopak? V takovém případě by nebyl problém uložit např. unikátní klíč (ten by se mohl ukládat do cookies), k němu další informace (IP, prohlížeč, ...) a v případě připojení na stránku pak kontrolovat, zda se uživatel přihlásil z druhého webu.

Popř. scriptem volat druhou stránku a tam automaticky přihlašovat.
Pietro
Profil
Ověřovat, jestli je uživatel již přihlášen na druhém webu není problém přes webovou službu. Musím ale zjistit identifikaci (např. uživatelské jméno nebo ID) tak, aby nemusel uživatel zadávat login znova. Na to se mi jeví ta možnost iframu dobrá. Dalo by se tím nastavit cookie. Díky Knighte.

o_O
Tohle bohužel možné není, ale na autentizačním (tj. hlavním) serveru se dá naprogramovat webová služba, která by odpověděla jestli je uživatel přihlášen či ne. Musí ale obdržet ten identifikátor, a v tom je ten problém. Knight měl dobrý nápad, ještě to ale musím domyslet...

Díky vám oboum
o_O
Profil
Pietro:
Stačí kontaktovat druhý server, předat mu parametry a je to. Nejlépe to ošetřit přes nějaký dynamický klíč.

Např:
function kontaktuj(){
  $ch = curl_init('http://www.example.com/secret.php?ID_uzivatele=...&SESSID=...&KLIC=...');
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  $vysledek=curl_exec($ch);
  curl_close($ch);
  
  return $vysledek;
}

Data pak získáte přes $_GET. Můžete využít i hlavičky.
Pietro
Profil
Jenom se teď dočítám, že nastavování cookie z požadavků jiných doménových jmen ve stránce může být uživatelem zakázáno...
Cituju z www.jakpsatweb.cz/enc/cookies.html
V případě, že by se cookie snažil nastavovat jiný objekt ve stránce (např. obrázek), který se ale do stránky načítá z jiné domény, jde o tak zvanou cookie třetí strany (third part cookie). Na některých prohlížečích je ukládání takových cookies omezeno nebo zakázáno -- záleží to na nastavení prohlížeče a na tom, zda server má P3P soubor.
Pietro
Profil
O_o
Teď Vás asi nechápu jak to myslíte. Na serveru A se uživatel přihlásí. Server A kontaktuje server B a řekne mu, že tento uživatel je přihlášen. Když ale pak uživatel přijde na server B, jak server B pozná, že se jedná právě o toho konkrétního uživatele?
o_O
Profil
Pietro:
jak server B pozná, že se jedná právě o toho konkrétního uživatele?
V případě mnou zmiňovaného postupu v [#5] se na serveru B v případě platné autentizace vytvoří session.

Můžete si to třeba zkusit. Zadejte do mé funkce URL serveru B (tam pak vyzkoušejte vytvořit session), zavolejte tuto funkci na serveru A a někde si vypište všechny existující sessions na serveru B.
Pietro
Profil
o_O:
To ano, ale prohlížeč uživatele nebude znát SESSID. V tom je ten problém. Nebudu moct nastavit uživateli cookie pro doménu serveru B.
o_O
Profil
Pietro:
Cookies nepotřebujete, na serveru B vytvoříte session a to session tam prostě zůstane. Nechápu, co na tom nechápete :-)

Příklad scriptu na serveru B:
<?php
session_start();
if(isset($_GET['ID_uzivatele']) && isset($_GET['KLIC']) && $_GET['KLIC']=='...'){
  if(!isset($_SESSION['user'])){
    $_SESSION['user']=array();
    $_SESSION['user']['id']=$_GET['ID_uzivatele'];
    $_SESSION['user']['blabla']='...';
    echo 'logged in';
  }else echo 'already logged';  
}else echo 'e403';

Moje funkce vrací i výstup, tzn. zjistíte, zda byl uživatel přihlášen.
Knight
Profil
o_O:
Ten druhý web se ale nějak musí dozvědět, že příchozí uživatel patří k té session. A vzhledem k tomu, že při přesunu mezi doménami se nám nepřenáší cookies, tak by musel být identifikační řetězec v URL. A to není zrovna kůl, i z toho hlediska, že uživatel nemusí přejít pomocí našeho odkazu.

Pokud by selhal image i iframe (ten by z principu měl vždy fungovat), tak bych se na pohodlí uživatele asi vyprdnul - když chce tak moc anonymitu prohlížení, ať se přihlásí několikrát.

Ještě by tu byla možnost při přihlášení natvrdo přesměrovat na druhý web, tam zapsat cookies, a přesměrovat se zase zpět, ale to je už extrém.
o_O
Profil
Knight:
Eh, nějak stále tápu, co tím myslíte. Ta session se vytvoří na serveru B -> když tam návštěvník přijde, tak jí prostě bude mít. Je to stejné jako by jste session nastavovali na stejném webu, jen s tím rozdílem, že se musí zavolat ten script.
Pietro
Profil
o_O:
Ano, server by byl nastaven. Ale očekával by $_GET['ID_uzivatele']. Ale jak chudák uživatel bude toto ID posílat na server? Jak ho zjistí?
o_O
Profil
Pietro:
Jaký uživatel, proboha? Odešle to server při přihlášení na serveru A. Stačilo jen přečíst si mou funkci v [#5]. Navíc uživatel nic posílat neumí, nemůže a nezjistí. Od toho existují serverové scripty - vykonají se již na serveru.
Pietro
Profil
o_O:
Ne, vy nás stále nechápete. Uživatel ABC s ID 123 se přihlásí na serveru A. Fajn, je přihlášen, server A zajistí, aby se pro pro něj nastavila na serveru B session. Uživatel brouzdá pro serveru A a najednou ho napadne, že přejde na server B. Zadá adresu serveru B do prohlížeče jako www.serverB.cz a dá enter. Server B má uživatele za nepřihlášeného a vytvoří mu nové session. Už chápete o co nám jde?
o_O
Profil
Pietro:
server A zajistí, aby se pro pro něj nastavila na serveru B session
Tak co je za problém?

Server B má uživatele za nepřihlášeného a vytvoří mu nové session
Jak může mít server B uživatele za nepřihlášeného, když mu server A již poslal požadavek na zaregistrování session?
Pietro
Profil
o_O:
Pardon, ale já už nevím jak to lépe vysvětlit. Buď já, nebo vy chápeme jiný problém. Prosím vysvětlete mi, jak se člověk který je přihlášen na serveru A, zadá do webového prohlížeče adresu serveru B a stiskne ENTER, jak se najednou stane na serveru B přihlášen. To stále nechápu.

Session je jen pole hodnot uložené na serveru pod nějakým identifikátorem. Tento identifikátor musí klient (resp. prohlížeč uživatele) na server ale odeslat. Zpravidla se jedná o proměnnou SESSID, která se posílá z COOKIE, ale může se posílat i v GET. Když se ale nepošle a v kódu je session_start(), vytvoří se SESSION pole nové.
Takže otázka je a už několik příspěvků výše byla, jak zajistit, aby klient (prohlížeč uživatele) tento údaj znal a na správném serveru (serverB) odesílal?
Oceňuji Vaši snahu o vcelku přínosnou diskuzi, ale mám stále pocit že nechápete v čem je ten zakopaný pes. Anebo já nechápu Vámi navrhované řešení...
Pietro
Profil
Ještě mne napadlo ukázat to na příkladu. Prosím opravte mne, pokud je můj scénář chybný.

Já jako uživatel si otevřu www.serverA.example. Tam na mě vyskočí přihlašovací formulář. Vyplním svoje údaje a odešlu.
Server zjistí, že moje jméno a heslo je správné, a pomocí funkce kontaktuj() odešlě HTTP požadavek na vytvoření session na serveru www.serverB.example. Ten jej vytvoří, a přidělí mu SESSID 1a2b3c4d.
Načte se mi stránka, na které je psáno, že jsem přihlášen (stále na serveru A). Brouzdám si tak po serveru A, a za pět minut mě to přestane bavit a přejdu zadáním adresy do prohlížeče www.serverB.example.
Server B si přečte HTTP požadavek a zjistí, že neposílám žádný SESSID ani v COOKIEs, ani v GET. Proto mi vytvoří novou, prázdnou SESSION s SSID w9x8y7z6. A protože je tato session prázdná, bude chtít, abych se přihlásil.

Co je tedy na tomto scénáři špatně? Co je to vodítko, díky kterému po zadání adresy serverB.example do prohlížeče ten automaticky odešle správné SESSID (1a2b3c4d)? To je to, co mi stále není jasné.
Knight
Profil
o_O:
Problém je, že i ta session potřebuje pro běh cookies (nebo řetězec v URL). Když nastavíte session, tak se do cookies přidá PHPSESSID, které obsahuje identifikační řetězec (např. ogdh2bl86k1ivk19dm00ek7ld0), podle kterého server ví, že jste to vy, a můžete dotazovat uložené proměnné v $_SESSION.

Pokud dotážete externí skript nastavující sessions, tak docílíte pouze toho, že se zapíše session na tom vzdáleném serveru, ale nikoli už PHPSESSID u uživatele (takže s ní nepůjde pracovat).

To máte třeba jako schránku v bance, když si ji založíte, dostanete klíč a můžete ji vybírat. Když ji ale založí někdo jiný, a nedá vám od ní klíč, tak ji vybírat nemůžete.
o_O
Profil
Pietro:
Nechápete mnou navrhované řešení.

Návštěvník na serveru A zadá přihlašovací údaje, klikne na přihlášení. V případě, že zadal údaje správně, se odešle mojí funkcí dotaz na server B, v kterém se následně údaje zpracují (metoda get) a vytvoří se session na serveru B - cookies se vytvoří.

A vážně nechápu, co na tom nechápete. Zkuste si prostě mou funkcí zavolat Váš jiný server - nějaký nově vytvořený soubor v kterém bude prostě jen:
<?php
session_start();
$_SESSION['nechapavyTest']='Hodnota';
?>
a následně si tu session na cizím serveru nechte vypsat (v jiném souboru než jí nastavujete ovšem):
var_dump($_SESSION);

A to nechápání je pravděpodobně jen lenost podívat se na funkci cURL - volá server - server zpracovává požadavek a tudíž může vytvořit session, stejně jako iframe, obrázek nebo cokoliv jiného. Rozdíl mezi tím ovšem je, že moje verze je jednodušší na zabezpečení a nepoužívá zbytečně neexistující obrázky.
Pietro
Profil
Prosím, udělal jsem živý příklad a otestoval jsem to.

http://servera.hubik.net/index.php (zdrojový kód: http://servera.hubik.net/index.phps)
volá http://serverb.hubik.net/secret.php (zdrojový kód: http://serverb.hubik.net/secret.phps)
SESSION dump: http://serverb.hubik.net/index.php (zdrojový kód: http://serverb.hubik.net/index.phps)

Session sice vytvoří, ale jen při zpracování secret.php se dá číst. Pokud v jiném souboru se budete chtít dotázat na session, bude prázdné.
Pietro
Profil
Tady nikdo nepochybuje, že se SESSION na serveru nastaví. Já s Knightem se Vás pokoušíme přesvědčit, že nemáte od session správný identifikátor.
Medvídek
Profil
Pietro:
Pokud by se jednalo pouze o subdomény, tak to lze řešit nastavením cookies pro všechno na doméně.
Pietro
Profil
Medvídek:
Ne, toto je jen modelový příklad. Jde o různé domény.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0