A zase session

Tak jsem právě prošel stovky starých přízpěvků na toto téma a nějaké ty články a nejsem z toho moc moudrej. Asi se budu muset vnořit do knih.

Udělal jsem si session autorizaci, vpohodě mi to funguje, ale trochu mi to uniká. Když jsem prohlížel třeba článek na www.reboot.cz, tak tam při kontrole oprávněnosti přístupu zjišťují id a čas s údaji v databázi. Proč to? Vždyť čas si můžu uložit do session a co s tím ID? Prostě zkontroluji, jestli je zapnutá: if (isset($_SESSION['auth']))
Tak to dělají v článku na www.interval.cz. Pro změnu tam ale zase při volání nějakého skriptu vkládá za adresu konstantu SID (např test.php?SID). Proč to? Jak je to teda s tím ID a neopomíjím kontrolovat něco, co bych měl?

A další. Session využívají cookies. Co když si je člověk vypne. Jak to tedy je. Někdo tu v dřívějších příspěvcích psal, jak je výhodné pro uložení proměnných využít session místo cookies.

Dik za odpovědi.
Oprava: ne přízpěvků, ale příspěvků
session jsou data ulozeny na servru spojeny s nejakym id. pokud je pozadavek od klienta ktery jeste nema prideleny id tak se mu prideli. problem je s tim, jakym zpusobem se pak to id u klienta ulozi a jakou cestou se dostane k servru. asi nejjednodussi a nejpohodlnejsi metoda je pouzit cookies, pokud je klient nepodporuje tak nezbyva nic jinyho nez to id pripojit za kazdy link na strance..
no nicmene v praxi se ne to muzes uplne vykaslat, to pripojovani SID za linky se dela automaticky (pokud je zapnuty use_trans_sid), ty cookies samozrejme taky.
takze za normalnich podminek uplne staci session_* funkce.
session a cookies vubec nemuzes srovnavat, pouzivaji se na ruzne veci. cookies jsou nejaka data ktera ti posle klient a ty se nemuzes spolihat na to ze pochazeji z tveho skriptu (i kdyz to tak vetsinou byva:)...
4bohdan: dík za vysvětlení a trochu to rozeberu

Jsem rád, že jsi mi potvrdil, že se to SID dělá automaticky.

Co se týče srovnání cookies vs. session, tak já jsem je rozhodně nechtěl srovnávat. Jen mě udivilo, že session využívají automaticky cookies a tudíž mi unikala ta výhoda spojená s faktem, že si je někdo může vypnout ale pak by nefungovaly ani session. Ale už je mi to jasný.

Takže poslední věc. Když mám v nějaké stránce skrip kontrolující přístup, stačí pouze provést:
if (isset($_SESSION['name']))
nebo musím ještě porovnávat ID s nějakým uloženým ID?
(na www.reboot.cz to dělají, ale na www.interval.cz ne)
Jde o to, že podle mě by se to ID nemuselo kontrolovat, pokud ovšem nelze nějakým způsobem podstrčit skriptu cizí informace (což by možná šlo).

Teda teď jak to po sobě čtu, tak mi to začíná docházet. Proto Lukasik když tu kdisi cosi psal o session, tak uváděl, co všechno o uživateli ukládá za kontrolní informace (ID, IP, ...). Aby někdo nemohl někdo něco podsunout. Takže jsem si už asi odpověděl.

Každopádně dík za našlápnutí mého mozku :-)
Já to vždycky dělal tak, že jsem si "id" přihlášeného uživatele uložil do databáze spolu s "platností" +20 min, a "id_uzivatele" z tabulky uživatelé.

Při každém vstupu na chráněnou stránku jsem jen zjistil, jesltli prohlížeč s tímto "id" je v databázi a jestli jeho "platnost" není menší než aktuální čas. Zároveň jsem smazal všechny už neplatné "id" z databáze.
Odhlašování se rovnalo vymazání záznamu z databáze.

Nikdy jsem se moc nezabýval tím, jestli to není zbytečně složité, ale poslední dobou jsem vidím, že všude dělají autorizaci prostě tím
if (isset($_SESSION['name'])). Vždycky jsem v to měl jakousi podvědomou nedůvěru :-), ale když tak uvažuju, tak to asi bezpečnoste vyjde úplně nastejno, ne?

Jaké jsou vaše názory, nebo jak to máte vy? Docela mě to zajímá, a hlavně mě těší, že konečně někdo přišel s konstruktivním a jasně formulovaným dotazem :-)

PAVEL
Ha, teď jsem se podíval na ten reboot.cz (jinak tam nechodím, pač tam nic o PHP není) a zjistil jsem, že mluvíš přesně o těch skriptech, se kterými jsem před rokem s začínal :-)

Časem mi ale došlo, že ten autor, co to psal, v tom asi úplný profesionál není. Má to spoustu nedostatků a chyb. Troufám si říct, že bych to teď napsal lépe. Hlavně mě trápilo to, že má formulář i skript autorizace ve stejném souboru. Pak, kydž listuješ v historii zpět, tak se tě pořád ptá, jestli chceš odeslat data znovu atd.

Vyřešil jsem to tak, že skripty, ketré mají proběhnouz jen jednou - přihlášení, odhlášení, změna databáze - mám jako samostatné soubory, bez výstupu, takže se ani neuloží do historie prohlížeče. Tohle by mě taky zajímalo, jak to dělají ostatní, ale mě se zdá, že operace, která má proběhnout jen jednou musí být v samostaném souboru.

PAVEL
no..je to trochu problem.. kdyz as normalni http autorizaci tak se sice pokazdy posila nesifrovany (maximalne hashovany-md5) heslo, ale aspon se to posila v hlavicce. v porovnani s tim autorizace pomoci session (nebo presneji - mas jeden formular, po jeho vyplneni se poslou username+pass na server kde se zalozi session) sice heslo pres net posila jen jednou, pak ale posila dal session id ktere by mohl nekdo ukrast.. situace je o to horsi ze se session id casto posila jako parametr v url, takze se uklada na vsech ruznych mistech pres ktery ten pozadavek jde (historie prohlizece, logy na proxyne, logy na servru...).
bez ssl proste dobre zabezpecenou stranku neudelas, jediny jak muzes trochu vylepsit tu autorizaci pres session je generovat session id treba na zaklade ip adresy + nahodne cislo, pak (kdyz pokazdy proveris jestli session id odpovida ip) by 'utok' musel jit ze stejne ip adresy. no ale myslim ze jestli delas nejaky normalni chat nebo aplikaci podobnyho typu tak je uplne jedno jakou metodu pouzijes.. a jestli delas spravu konta :-) nebo tak neco tak bych to urcite pojistil ssl..
Tak správu konta zrovna nepotřebuju. Teď mi jde o přístup do administrátorské sekce stránek. Nejspíš nikoho nenapadne prolamovat zrovna mé stránky. Horší je, že třeba u stránek nějaké firmy by takové informace mohly někomu pomoct.

PAVEL
tak me napada jak je to vlastne na wz s ssl? asi jsem moc narocnej, co.. :-)
Ad SSL: už se tu někdo ptal, ale bojím se, že seš moc náročnej.

Jinak přesně jsem si myslel, že to tak je, jak napsal bohdan. Takže pokud mi zas nejde tolik o tu bezpečnost, myslím, že bohatě stačí provést kontrolu:
if (isset($_SESSION['name']))
Má to i tu výhodu, že se nemusí vůbec pak otvírat databáze, jelikož když neukládám pro kontrolu ID, nemusím ani čas, neboť ten prostě můžu hodit jako proměnnou taku do session, což mi přišlo jako docela fajn nápad.

Jinak dík Pavlovi za pochválení dotazu. Já jsem se totiž probíral starejma příspěvkama o session, ale nenašel jsem tam nějakej závěr, tak jsem to chtěl schrnout (pro příští generace :-))
Přesně, taky jsem došel k názoru, že session je nejlepší, hlavně díky své jednoduchosti. Riziko to s sebou určitě nese, ale nic lepšího pro takovéto "menší aplikace" stejně asi neuděláš. Možná by pomohla ještě nějaká ta kontrola navíc (viz. co píše Bohdan).

Co se týče toho if (isset($_SESSION['name'])) versus ukládání id do databáze, tak to je asi úplně stejné. Nebezpečí se skrývá jinde - právě v tom putování session_id po síti.

btw: Tento článek jsem pochválil, protože mi přijde opravdu jako jeden (hodně) mála, které tady v tomto fóru za něco stojí :-)

PAVEL
Kdyz se bavite o session tak mi prosim poradte jak se da udelat aby mi nejaky odkaz odkazovat na index.php?page=10! chtel bych to ukladat do session ale podlemne to nejde!
Tak to jsem nepochopil, můžeš to přiblížit.

> jak se da udelat aby mi nejaky odkaz odkazovat na index.php?page=10
<A href="index.php?page=10">stránka 10</A>
jo ale ja nechci aby tam bylo to page=10
<a href='index.php?SID'>stranka 10</a>
a do sesion chci dat ze page=10
Takže chceš, aby si měl proměnnou $page, kterou dáváš do URL přístupnou jako session.

To, co jsi napsal, je nesmysl. SID je konstanta, která obsahuje identifikátor prohlížeče (např. SID=84271475e1f4cc7c686c9f0974a86af8), ale ty chceš jinou proměnnou.

Potom použij v prvním skriptu tohle:
<?
session_start();

$_SESSION['page'] = 10;
?>

V kterémkoliv jiném budeš mít potom tuto proměnnou přístupnou.
<?
session_start();

if (IsSet($_SESSION['page'])): // jen zkouska
echo "Hura, uz to funguje !!! :-)";
$page = $_SESSION['page'];
endif;

echo "<A href=\"index.php?page=$page"\>Stránka $page</A>";
?>

Samozřejmě nemusíš získávat z $_SESSION['page'] proměnnou $page, ale já jsem ti to tak napsal, aby to bylo lépe vidět.

Jinak zkus si něco přečíst, tak to nejlépe pochopíš.

PAVEL
nevim jestli jsem uplne pochopil pavlovu myslenku, ale dal bych si pozor na pojmenovavani promennych. z bezpecnostich duvodu (je to docela logicky,99%skriptu by jinak muselo na zacatku delat kontrolu) se promenna ktera uz je registrovana jako session neda pouzit jako parametr url (ani v post) - resp. da, ale neni registrovana jako globalni. mozna je lepsi nedavat do get stejny promenny jako do session, nebo pouzivat vsude delsi formu ($_GET,$_POST,$_SESSION)..
Mno ja si napsal vlastni funkce na session a je to v pohode.... Sice je to jemne slozitejsi, ale jinak dobry... Nejlepsi by bylo asi jet pres SSL nebo sifrovat pripojeni nak jinak, protoze je pravda, ze sessionid se da snadno chytit.... Trochu lepsi by ho mozna bylo posilat metodou POST, ale to na to me napada reseni jedine pres JS....
Když to teď čtu, tak vidím, že ten skript nemá žádný smysl. Proč vlastně přenášet v session proměnné informaci page=10, a pak ji vkládat do všech URL? Asi jsem nepochopil původní Romanův dotaz:

> Kdyz se bavite o session tak mi prosim poradte jak se da udelat aby mi
> nejaky odkaz odkazovat na index.php?page=10! chtel bych to ukladat
> do session ale podlemne to nejde!

> jo ale ja nechci aby tam bylo to page=10
> <a href='index.php?SID'>stranka 10</a>
> a do sesion chci dat ze page=10

Nicméně, když pomineme význam skriptu, tak jinak to správně je, ne? Myslím registraci session proměnné a její získávání na další stránce.
no ja nevim, at delam co delam tak ten dotaz nechapu :-)
2TheRoot:
no kdyz vypnes automaticky pridavani sid za url a spolihas na cookies tak to funguje na stejnym principu jako post data..
kodovat to je dost silena myslenka, ale kdyz tam das tu kontrolu ip (vcetne lan ip u siti) tak to relativne bezpecny je..
(myslim generovat session id jako treba md5 z (ip + nejakeho kodu) + nahodna sekvence, treba kus uniqid..)
no ale ssl je ssl, vubec se to neda srovnavat..
Ale cookies nema zapnuty kazdej... jinak to s tou IP je celkem bezpecny az na model, gdy sou treba 3LAN pripojeny na servery WAN a server WAN teprve do netu, to uz ti tole nepomuze, protoze v tech trech LAN muze bejt stejna IP... A co treba proxy? Gdyz pak bude negdo pouzivat proxy treba mistralu nebo tag, nastava taky dalsi problem, myslim, ze v pozadavky proxy se LANIP neuklada... Na to bych moc nespolihal... jinak samozrejme SSL je SSL....
no..vnoreny lan a podobny modely zas tak casty nejsou, proxyna je trochu castejsi problem :) ..
koukni se na $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"], je to z hlavicky ziskanej seznam ip pres ktere to slo..
no nicmene necemu co ti nekdo poslal v havicce se zrovna moc verit neda, i kdyz...kdo by si daval tu praci
Mno gdyz by ti to negdo chtel hacknout, tag no problem.... Jinak proste co je potreba bezpecny, to sifrovat...
Dovolím si přerušit tok vaší diskuse a ještě se na něco zeptám.

Pomocí session ošetřím přístup na stránky, ale jak zabráním, aby se mi někdo dostal k určitým dokumentům. Tohle totiž řeší HTTP autorizace a nevím jak jinak zabránit vstupu do adresářů. Mám totiž download adres v různých formátech (např xls atd.) a nechtěl bych, aby se k nim někdo nepovolaný dostal.

Dík za nápady a odpovědi.
Slo by napsat PHP script, kterej by vyzadoval heslo a gdyz bys chtel neco stahovat, tag bys ho zavolal s heslem a ID souboru a on by overil, estli je heslo platny a pag by na zaklade porovnani ID se zaznamem v DB otevrel soubor a vratil obsah souboru, samozrejme fsechny soubory by meli velmi nepravdepodobnou adresu, nebo by byli proste nepristupne pres protokol HTTP....
Tento postup je mi jesný, ale mě jde o zabránění přístupu zvenčí a nepravděpodobný název souboru nepovažuji za dobré řešení (to je pouze proti běžným uživatelům). Takže jak udělat to "prostě nepřístupné přes protokol HTTP" (ale abych se k tomu zase nějak dostal).