Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Bezpieczna sesja
Forum PHP.pl > Forum > Przedszkole
ttdd
Przeglądając temat http://forum.php.pl/index.php?s=&showt...st&p=971557 natrafiłem na post !*!, a dokładniej chodzi mi o bezpieczeństwo sesji.

Mam na swojej stronie przy logowaniu do panelu administracyjnego coś takiego (po poprawnym wpisaniu danych):
  1. $_SESSION['admin_logged'] = true;

Do tej pory wydawało mi się to w miarę bezpieczne, ale po przejrzeniu w.w tematu zacząłem mieć wątpliwości.

Tak sprawdzam czy administrator jest zalogowany i jeśli tak wyświetlam odpowiednią stronę:
  1. if (!isset($_SESSION['admin_logged'])) {

Czy taki sposób jest bezpieczny?
GoOx
Ja bym podczas logowania jeszcze generował id sesji który będzie w dodatek zakodowany np przez md5 i umieszczał bym go w linku a potem sprawdzał czy id sesji zgadza się z id w bazie danych oraz id które mamy w sesji.
!*!
Cytat
i umieszczał bym go w linku a potem sprawdzał czy id sesji zgadza się z id w bazie danych oraz id które mamy w sesji.

O losie... A jak ktoś skopiuje link dla ktosia innego to już nie zadziała...

Zapomnij o przesyłaniu w linku czegokolwiek co dotyczy sesji, to jakiś chory i stary wymysł. Zrób funkcje, która będzie zamiennikiem dla

Cytat
$_SESSION['admin_logged'] = true;


A w tej funkcji sprawdzaj czy właśnie dana sesja istnieje, czy zgadza się odstęp czasu dla ostatniej akcji i czy zgadza się user agent z IP, dodatkowo właśnie jakiś token, z md5/sha1 i powinno być ok, to skąd będziesz pobierać dane, czy sesja/czy baza, pliki czy cokolwiek to już nie ma znaczenia.
Dominator
Według mnie jeszcze możesz zrobić tak, że jeśli logujesz się z loginu np: "ttdd" to w kolumnie "logged" jest 1, a jak się wylogowujesz to 0 smile.gif I gdy kolejna osoba próbuje się zalogować na te dane podczas gdy w kolumnie "logged" będzie 1 to będzie stosowny komunikat biggrin.gif
Gość
ok już wiem co i jak, dzięki za pomoc smile.gif
greycoffey
Cytat(!*! @ 25.06.2012, 19:47:15 ) *
A w tej funkcji sprawdzaj czy właśnie dana sesja istnieje, czy zgadza się odstęp czasu dla ostatniej akcji i czy zgadza się user agent z IP, dodatkowo właśnie jakiś token, z md5/sha1 i powinno być ok, to skąd będziesz pobierać dane, czy sesja/czy baza, pliki czy cokolwiek to już nie ma znaczenia.

Czy naprawdę nikt tu nie rozróżnia samej idei działania sesji a jej implementacji? Chyba "trzymanie danych w sesji" znaczyło dla Ciebie "trzymanie danych używając domyślnej implementacji sesji w PHP", która de facto jest oparta NA PLIKACH. Można napisać mechanizm sesji obsługujący róźne źródła danych sesyjnych - nie ma znaczenia czy pliki, baza danych czy chmurowy pojemnik na dane.

Cytat(Dominator @ 25.06.2012, 19:51:29 ) *
Według mnie jeszcze możesz zrobić tak, że jeśli logujesz się z loginu np: "ttdd" to w kolumnie "logged" jest 1, a jak się wylogowujesz to 0 smile.gif I gdy kolejna osoba próbuje się zalogować na te dane podczas gdy w kolumnie "logged" będzie 1 to będzie stosowny komunikat biggrin.gif

Tak, wyłącze przeglądarke, sesja mi minie, nie zmieni się wartość kolumny logged i już się nei zaloguję. Takie mechanizmy blokujące trzeba dokładnie przemyśleć.

Generalnie rzecz ujmująć, domyślna implementacja sesji jest bezpieczna na manipulacje, jeśli nie jesteś na shared hostingu, gdzie wszystkie sesje trzymane są w jednym katalogu (w tym wypadku możesz zmienić katalog w którym są przechowywane dane sesyjne) oraz gdy nie piszesz bezsensownego kodu pozwalającego na zmienianie danych sesyjnych w sposób niezamierzony.
!*!
greycoffey - czepiasz się, plik plikowi nie równy, tak jak sesja, sesji. To tylko nazwy, a implementacja z zastosowaniem to inna bajka.
piotrooo89
miałem nie brać udziału w takich flame no ale na chęciach się skończyło...

powiedz co jest przesłanką do tego, że chcesz w jakikolwiek zmieniać coś w mechanizmie sesji? bo ja sensownego powodu nie widzę, jak wspomniał @greycoffey można zmienić miejsce zapisywania sesji ale po jakiego czorta zmieniać, cały mechanizm? bo jeśli nie masz konkretnego powodu uważam za głupotę zmieniać coś natywnego, na jakieś własne widzi mi się.
greycoffey
@up (tzn. !*!): Własna funkcja, która rozróżnia użytkowników to też sesja. Zresztą własna funkcja sesjopodobna bez podłączenia ją pod session_set_save_handler() to wyważanie otwartych drzwi w większości przypadków.
!*!
piotrooo89 dlatego napisałem że greycoffey czepia się, bo nic nie wniósł do tematu, odnośnie mojej wypowiedzi. eot.
piotrooo89
no moim zdaniem się nie czepia, tylko pokazuje zły tok myślenia niektórych. dał przykład jak można zaimplementować zmienne sesyjne, ale po tym dał wszystkim pstyczka w nos i powiedział po co tak robić skoro natywny mechanizm jest OK.
ttdd
to sposób, który podał !*! jest dobry? bo już się pogubiłem w tym wszystkim, a właśnie zacząłem pisać funkcje.

I od razu mam pytanie bo jednak do końca nie zrozumiałem. Napisałem coś takiego:

(logowanie)
  1. $session = session_id();
  2. $session = sha1($session);
  3. mysql_query("UPDATE `admins` SET `session_id` = '$session' WHERE `admin_login` = '".mysql_real_escape_string($_POST['admin_login']."'");
  4. check_admin_logged($session);

Tu chyba jest wszystko dobrze?

I funkcja sprawdzająca:
  1. function check_admin_logged($session) {
  2.  
  3. if (isset($session)) {
  4. $admin_session = mysql_fetch_assoc(mysql_query("SELECT `session_id`, `admin_login` FROM `admins` WHERE `session_id` = '$session'"));
  5. if ($admin_session === ?) {
  6.  
  7. }
  8. }
  9.  
  10. }

Nie wiem co dalej i czy w ogóle idę w dobrym kierunku smile.gif
greycoffey
Złe podejście do tematu. Generalnie domyślna implementacja sesji w PHP jest dobra, ale dla celów edukacyjnych warto napisać własną - poczytaj o session_set_save_handler, jak stworzysz odpowiednie funkcje i zlaczysz je w tej funkcji, możesz korzysta z własnej implementacji jak z domyślnej (operacje na $_SESSION, funkcje session_start(), session_destroy() etc.).

Po pierwsze, opierasz się na istniejącej sesji, zamiast stworzyć własną, co wprowadza niezły bajzel.
Po drugie, hashujesz hash (w 99% przypadków session_id() zwraca ci md5() jakiegoś pseudolosowego ciągu).
Po trzecie, tworzysz sztywne pola. We własnej implementacji najlepsze według mnie będzie struktura (taki pseudosql bo nie chce ci mieszac pewnych instrukcji dostępnych tylko w PgSQL):
  1. Tabela sessions:
  2. sessionid | unikalny ciąg w bazie o stałej ilości znaków, najlepiej hash losowego numeru, ten hash wysyłasz użytkownikowi w COOKIE
  3. internalid | wewnętrzne id, klucz obcy do sessions_values(internalid), unikalny, AUTO_INCREMENT, TO wewnętrzne id którym posługujesz się w relacjach bazodanowych
  4. useragent | przechowujesz useragenta którego będziesz sprawdział w funkcji open() sesji
  5. ip | jak wyżej
  6. lastaction | timestamp ostatniego żądania, jeżeli większy od obecnego o X sekund (proponowałbym 1800), niszczy sesje (a co za tym idzie dane sesyjne w pobocznej tabeli)
  7.  
  8. Tabela session_values:
  9. internalid | już wyjaśnione
  10. KEY | klucz danej sesyjnej, unikalny dla danego internalid (możesz dać w bazie klucz na internalid oraz KEY RAZEM lub sprawdzać z poziomu PHP)
  11. value | wartość danej sesyjnej

Po czwarte, w miejscu ? chodziło pewnie o sprawdzenie czy funkcja zwraca 0 czy więcej rekordów. mysql_num_rows.
We wspomnianej na początku funkcji zobacz "Example #2".

EDIT: 2^8 post ;]
!*!
Pierw odpowiedz sobie na pytanie czy sesja trzymana w bazie jest Ci w ogóle potrzebna.
ttdd
Cytat(!*! @ 26.06.2012, 09:35:20 ) *
Pierw odpowiedz sobie na pytanie czy sesja trzymana w bazie jest Ci w ogóle potrzebna.


no a jak nie?

to ma działać tak:

przy poprawnym logowaniu zapisuje sobie session_id() do tabeli admins w polu session_id i time() w polu last_active i do tego zapisuje session_id w sesji tak? biggrin.gif W funkcji sprawdzającej czy administrator jest zalogowany sprawdzam czy istnieje ta sesja i czy jest taka sama jak ta z bazy + czas ostatniej aktywności.

dobrze myślę?
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.