Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: ad.3. - Sesje
Forum PHP.pl > Forum > PHP > Pro > Archiwum Pro
dragossani
Jak słusznie zauważył Seth, przydałyby się osobne wątki. Niniejszym powstał pierwszy.
Cytat
apropos sesji to tu jest narazie beta test;) mojego artykulu

Przeczytałem i muszę powiedzieć, że mam mieszane uczucia. Z jednej strony faktem jest, że artykuł o tej tematyce zainteresuje osoby początkujące i średniozaawansowane - i sądząc po treści, dla takich został napisany. Jest wprowadzenie i wszystkie podstawowe informacje. Z drugiej strony, osoby bardziej zaawansowane często odkrywają w sesjach sporo nieznanych im elementów. Uważam, że skoro powstaje taki artykuł to rozdziały bardziej zaawansowane też powinny się w nim znaleźć. Za chwilę napiszę dokładniej o co mi chodzi, a na razie parę uwag do tekstu (jeśli można ofkoz :wink: ).
Czytając odnoszę wrażenie, że autor zakłada, że php u użytkownika ma standardowe ustawienia. To w sumie słuszne założenie, ale nie jest zrealizowane konsekwentnie. W rozdziale "jak to działa?" czytamy: "Zmienne i ich wartości zostają zapisane do specjalnych plików po stronie serwera." To prawda, ale tylko przy ustawieniach domyślnych. Dane sesji możemy przecież trzymać gdzie nam się podoba - w bazie danych albo na ftpie w archipelagu trynidad tobago. Kwesta zdefiniowania funkcji wejścia-wyjścia. W "Bezpieczeństwo" czytamy: "Istnieje jednak jak juz wyżej wspomniałem możliwość "oszukania" skryptu gdy wykorzystujemy funkcje session_register() do tworzenia zmiennych sesyjnych. Jako, że funkcja tworzy zmienną super globalną istnieje możliwość przekazania odpowiedniej zmniennej w URLu przez co wartośći zostaną przekłamane i umożliwią np. dostęp do strzeżonej hasłem strony." To oczywiście też prawda (no może z wyjątkiem określenia "super globalną" - raczej "globalną", superglobalne to są tablice takie jak $_POST), ale akurat nie przy ustawieniach domyślnych. Domyślnie zmienne rozpakowywane są w następującej kolejności: EGPCS (Enviroment, Get, Post, Cookie, Session) - kolejne tablice nadpisują zmienne z poprzednich. Skoro tak jest to nie da się nadpisać zmiennej sesyjnej wklepując coś w adresie, ani nawet tworząc fikcyjnego post-a. Dodam, że nie widzę powodu zmiany tych ustawień i prawie u wszystkich wyglądają one w ten sposób. Nie chce przez to powiedzieć, że należy używać register_globals - sam jestem ich przeciwnikiem, ale skoro już powstaje artykuł to niech będzie precyzyjny. W "co potrzebuję, żeby używać sesji?": "Aby sesja poprawnie działała należy w pliku konfiguracyjnym php ustawić session.save_path". Skoro mówimy o ustawieniach domyślnych to ścieżka już tam jest. Oczywiście warto ją zmienić, ale to już temat do rozdziału "bezpieczeństwo". Nie wiem dlaczego transparentne przekazywanie identyfikatora jest w artykule prawie nieopisane. Dla początkującego jest to przecież bardzo wygodny mechanizm. Cookie zawsze można wyłączyć, a autodopisywanie SIDa do adresu jest na początek ok. We "wskazówki" czytamy: "W sesji nie należy przechowywać dużej ilości danych". Hmm... A dlaczego nie? Przecież to takie samo źródło danych jak każde inne. Utarło się, że przechowujemy tam tylko identyfikatory itp. ale równie dobrze mogłoby być tam co innego. Fakt, że jeśli sesja chodzi na plikach to jest mało wydajna, ale jeśli chodzi na bazie danych to już na prawdę nie widzę przeszkód... smile.gif
Mam nadzieję, że autor nie ma mi za złe tych uwag - generalnie artykuł mi się podoba biggrin.gif
Co powinno się jeszcze w nim znaleźć? Moim zdaniem kolejny rozdział o kwestiach trudniejszych. Przede wszystkim opis jak napisać uchwyty dla sesji przechowywanych w bazie danych (źródło: "PHP4 Aplikacje", albo zagraniczne artykuły w sieci), informacje o ukrywaniu identyfikatora sesji w mniej typowych miejscach - w ścieżce dostępu (ustawienia Apache'a i odpowiedni skrypt) oraz w nazwie domeny (ustawienia DNS'a oraz odpowiedni skrypt). Parę słów o przekazywaniu kluczowych zmiennych, takich jak identyfikatory rekordów bazy danych, między stronami (zagadnienie blisko spokrewnione) czyli np. jak zaszyfrować zmienną przed wysyłką (np. przez MD5), a potem przy wyciąganiu z bazy danych użyć MD5 wbudowanego w silnik bazy do znalezienia odpowiedniego rekordu. Dobrze byłoby wspomnieć o trudnościach czyli np. o tym, że tylko tablica $_SESSION jest superglobalna i można się do niej odwoływać wewnątrz funkcji. Inne metody wymagają globalizacji albo przekazywania w parametrach. Poza tym o problemach wynikających z nieusuwania ciacha u klienta (otwarcie sesji w osobnym oknie przy używaniu cookie rodzi szczególnie dużo problemów). Warto żeby ludzie wiedzieli czego unikać. No i może kilka słów o gc_probability. Można też opisać krótko kompletne rozwiązania takie jak phpLib, albo chociaż zrobić do takich opisów linki.
Jeśli będę mógł w czymś pomóc to jestem do dyspozycji. 8)

BTW, przydałaby się możliwość publikacji plików na tym forum. Chociaż takich po parę kilo - żeby nie wrzucać skryptów w treść.
Seth
Najpierw sprostowanie: ten artykul jest przeznaczony dla poczatkujacych.
nie zawarlem tam jakis zaawanoswanych tresci winksmiley.jpg ale dalem na dole linki gdzie mozna ich szukac (w WDVL'u jest link do phpLIB).

Co do przenoszenia danych sesji prosze poczytac w manualu o session_encode() i session_decode().

A co do wielkosci danych przenoszonych w sesjach to NIENALEZY umieszczac tam wielkich ilosci danych. Jest to najczestszy blad. A dlaczego nie nalezy: ano dlatego, ze powoduje to nadmierne zasmiecanie plikami sesyjnymi serwera. Spada takze wydajnosc. Dziwe sie wiec tobie dragossani, ze uwazasz, ze nie ma przeciwwskazan do przechowywania duzych ilosci danych w sesji.

Jesli chodzi o superglobalne (ta nazwa uzywana jest tez do zmiennych sesji z poziomu $... - przynajmniej wg. podrecznika) i podmienianie ich wartosci w artykule przedstawilem sposob w jaki mozna oszukac system wystarczy tylko go potestowac.

Jeszcze raz podkreslam: artykul przedstawia podstawowe informacje o sesjach i ich obsludze.

Tak, wiec jak juz jest ten topic to moze przedstawisz dragossani zaawansowane funkcje sesji aaevil.gif
dragossani
Widzę, że pomimo starań by mój tekst nie został odebrany jako wsadzanie kija w mrowisko, nie udało mi się tego uniknąć. smile.gif Ale do rzeczy.

Cytat
Najpierw sprostowanie: ten artykul jest przeznaczony dla poczatkujacych.
No ok, przecież napisałem że daje się to wyczuć i że taka była prawdopodobnie intencja autora. Nic w tym zdrożnego. Chodzi mi tylko o to, że brakuje w sieci polskojęzycznych artykułów przeznaczonych dla pasjonatów. Uznałem, że php.pl to portal który byłby w stanie zapełnić tę lukę. Gdybyś rozwinął artykuł o dodatkowe akapity (nie rezygnując z dotychczasowych) mógłby powstać tekst naprawdę uniwersalny.

Cytat
Co do przenoszenia danych sesji prosze poczytac w manualu o session_encode() i session_decode().
Szczerze mówiąc nie za wiele jest w manualu na ten temat. Moim zdaniem najbardziej interesującą wzmianką jest ta o session.serialize_handler. Kompilując php z obsługą WDDX'a możemy ustawić procedurę obsługi serializacji/deserializacji danych sesji za pomocą WDDX'a. Rozwiązanie jest o tyle interesujące, że dane w formacie WDDX są wyjątkowo elastyczne. Można łatwo operować na nich np. Javą, Pearl'em czy innymi. Przechowując dane sesji w bazie, w formacie WDDX, można pozwolić innym skryptom/programom dobierać się do nich i nie będą miały z tym problemu. Na przykład można uzyć Javy by monitorowała przebieg sesji i raportowała nieprawidłowości - taki front-end administracyjny.

Cytat
NIENALEZY umieszczac tam wielkich ilosci danych ... powoduje to nadmierne zasmiecanie plikami sesyjnymi serwera. Spada takze wydajnosc. Dziwe sie wiec tobie dragossani, ze uwazasz, ze nie ma przeciwwskazan do przechowywania duzych ilosci danych w sesji.
Napisałem przecież, że sesja na plikach jest mało wydajna. Powiedz mi: co za różnica czy wydajesz zapytanie do bazy o jakieś dane, które potrzebujesz na każdej kolejnej stronie i wrzucasz je do tablicy z której możesz je sobie wygodnie czytać, czy robi to za Ciebie php, używając sesji i napisanego przez Ciebie uchwytu do bazy danych? A co do zaśmiecania to chyba session.gc_probability oraz session.gc_maxlifetime do czegoś służą, prawda? Dodam, że trzymając sesje w bazie, można zrobić w nich porządek jednym zapytaniem. Tylko po co? Garbage collection działa sprawnie. Racja, że wiele osób popełnia błąd trzymając w sesji dane niepotrzebne, ale ich problemem nie jest kwestia rozmiaru danych, tylko zły projekt aplikacji - najprawdopodobniej wcale nie potrzebują w sesji wiele miejsca. A jak już jesteśmy przy wydajności to pamiętaj, że mamy jeszcze uchwyt "mm". Tam rzeczywiście nie byłoby dobrze trzymać dużej ilości danych, ale wydajność jest nieporównywalna z niczym.

Co do niebezpieczeństw związanych z register_globals to wypowiedziałem się już w poprzednim post'cie. Przetestowałem to - w starych wersjach php i w najnowszej. Pomimo register_globals=on nie da się nadpisać danych sesji url'em ze względu na kolejność rozpakowywania tablic. A jeśli u Ciebie działa to inaczej, to na prawdę nie wiem dlaczego.

Cytat
moze przedstawisz dragossani zaawansowane funkcje sesji
Chętnie coś o tym napiszę, tutaj na forum. Punktem wyjścia był jednak Twój artykuł. Chyba nie chcesz, żebym go pisał za Ciebie? rolleyes.gif

Tworzenie własnych, opartych na bazie danych, uchwytów dla obsługi sesji

Przykład jest oparty o współpracę z bazą MySQL ale równie dobrze można go przerobić tak, by uchwyty współpracowały z innym silnikiem bazodanowym. Oczywiście najlepiej byłoby, gdyby za komunikację z bazą danych odpowiadała odpowiednio wyodrębniona warstwa obsługi baz danych (vide phpLib) ale to osobny temat. smile.gif

Zapytanie MySQL'owe tworzące tabelę dla danych sesji:
Kod
CREATE TABLE sessions

    (

    id_sessions varchar(50) NOT NULL,

    data mediumtext NOT NULL,

    time_stamp timestamp(14),

    PRIMARY KEY (id_sessions),

    KEY time_stamp (time_stamp)

    );


Przykład biblioteki. Możemy ją nazwać powiedzmy "mysql_sesions.inc":
[php:1:3aebf2d40e]<?php
//Autorem kodu w niezmienionej postaci jest Tobias Ratschiller

$sess_mysql = array();
$sess_mysql["open_connection"] = true; // Nawiązywać połączenie z MySql'em przy uruchamianiu sesji?
$sess_mysql["hostname"] = "213.17.224.50"; // Nazwa hosa MySQL
$sess_mysql["user"] = "serwis"; // Nazwa użytkownika MySQL
$sess_mysql["password"] = "stialdev"; // Hasło do MySQL
$sess_mysql["db"] = "athena"; // Nazwa bazy gdzie przechowujemy sesje
$sess_mysql["table"] = "sessions"; // Tabela w której przechowujemy sesje

function sess_mysql_open($save_path, $sess_name)
{
global $sess_mysql;
// Otwórz połączenie do bazy MySql jeśli zmienna 'open_connection'==true
if ($sess_mysql["open_connection"])
{
$link = mysql_pconnect($sess_mysql["hostname"], $sess_mysql["user"], $sess_mysql["password"]) or die(mysql_error());
}
return(true);
}

function sess_mysql_read($sess_id)
{
global $sess_mysql;
// Pobierz z MySql-a dane przyporządkowane do sesji $sess_id
$result = mysql_db_query($sess_mysql["db"], "SELECT data FROM ".$sess_mysql["table"]." WHERE id_sessions = '$sess_id'") or die(mysql_error());
// Zwróć pusty łańcuch, jeśli dane sesji nie istnieją
if(mysql_num_rows($result) == 0)
{
return("");
}
// Znaleziono dane sesji, więc pobieramy je i zwracamy w wartości funkcji
$row = mysql_fetch_array($result);
mysql_free_result($result);
return($row["data"]);
}

function sess_mysql_write($sess_id, $val)
{
global $sess_mysql;
// Zapisz zserializowane dane ze zmiennej $val do bazy MySql
$result = mysql_db_query($sess_mysql["db"], "REPLACE INTO ".$sess_mysql["table"]." VALUES ('$sess_id', '$val', null)") or die(mysql_error());
return(true);
}

function sess_mysql_destroy($sess_id)
{
global $sess_mysql;
// Usuń z tabeli MySQL wszystkie dane sesji o identyfikatorze $sess_id
$result = mysql_db_query($sess_mysql["db"], "DELETE FROM ".$sess_mysql["table"]." WHERE id_sessions = '$sess_id'") or die(mysql_error());
return(true);
}

function sess_mysql_gc($max_lifetime)
{
global $sess_mysql;
// Stare sesje to takie, gdzie bierzący Unix Timestamp jest mniejszy niż (now - $max_lifetime)
$old = time() - $max_lifetime;
// Usuwamy stare dane z tabeli MySql'a
$result = mysql_db_query($sess_mysql["db"], "DELETE FROM ".$sess_mysql["table"]." WHERE UNIX_TIMESTAMP(time_stamp) < $old") or die(mysql_error());
return(true);
}

session_set_save_handler("sess_mysql_open", "", "sess_mysql_read", "sess_mysql_write", "sess_mysql_destroy", "sess_mysql_gc");
?>[/php:1:3aebf2d40e]

Od teraz możemy używać sesji przechowywanych w bazie MySql. Wystarczy na początku każdego skryptu dodać: include('mysql_sessions.inc');, a dalej już posługujemy się sesjami po staremu.

Dziś nie mam już siły klepać, ale napiszę jeszcze wkrótce o nietypowych metodach przekazywania identyfikatora sesji. Chyba, że ktoś inny zrobi to za mnie - do czego zachęcam.
Seth
Sorry, dragossani za poprzedni post, mialem troche zly humor winksmiley.jpg
Do tego co napisales dodam jeszcze dla zainteresowanych link do kolejnej ciekawej mozliwosci przechowywania sesji
:arrow: http://webdeveloper.pl/html/news/2002/03/07/294_3.php
poeta
Przyznam że polemikę: Seth vs. Dragossani - czyta się jak dobrą książkę Kinga

Dziekuję wam obu - bo wreszcie oświeciło mnie z grubsza w temacie sesji.

Może przydałoby się jeszcze kilka słów o tym jak najlepiej pod względem bezpieczeństwa korzystać z sesji albo chociaż kilka linków do przykładów stosowanych w życiu - ale to pewnie inny rozdział tej książki
poeta
Cześć

Wykorzystałem przekazaną przez was wiedzę i prawie wszystko u mnie działa z jednym wyjątkiem, podam w wielkim skrócie:


najpierw mamy: index.php
Kod
session_start();

$_SESSION['MAN']='KOWALSKI';

header("Location: index2.php");


index2.php to kilka ramek m.in content.php - tutaj hula że hej

Kod
include("../inc/mysql_sessions.php");

session_start();

echo $_SESSION['MAN'];


ale juz w ramce menu.php

Kod
include("../inc/mysql_sessions.php");

session_start();

echo $_SESSION['MAN'];


mam:
Warning: Access denied for user: 'apache@localhost' (Using password: NO) in /var/www/html/inc/mysql_sessions.php on line 42

czy to znaczy że nie mogę w dwóch ramkach równoczesnie korzystać z danych sesji

Z manuala nie wykumałem co może byc nie tak
rzseattle
Ja mam jeszcze lepsza jazde w ramkach ,,, uzylem powyzszego skryptu i

Kod
Warning: Cannot send session cache limiter - headers already sent (output started at c:foxservwwwsklepincpoczatek.php:2) in c:foxservwwwsklepinclewe.php on line 8


mimo ze:
Kod
session.save_handler = user

session.use_cookies = 0


czy ktos mi moze wyjasnic o co chodzi??
bo skoro sesje przeszly do bazy danych to jak do tego sie maja naglowki?questionmark.gif

I moze ponowie pytanie z forum php (skoru tu tak rozgozala rozmowa o sesjach) wiec:
Cytat
Mam problem w ramkach nie ma zmiennych sesyjnyc tzn gdy sprawdzam  
HTTP_SESSION_VARS na index.php to sa ale juz w samych ramkach ich ni ma co robic?
dragossani
Cytat
czy to znaczy że nie mogę w dwóch ramkach równoczesnie korzystać z danych sesji

TUTAJ jest mały test na działanie sesji w ramkach. Dopisz tylko we wszystkich plikach, przed każdym 'session_start()' linię: include("../inc/mysql_sessions.php");
U mnie działa zarówno w trybie domyślnym, jak i po zdefiniowaniu uchwytu bazodanowego. Jeśli ten kod zadziała u Ciebie to musisz się krytycznie przyjrzeć Twoim skryptom. Jeśli nie zadziała to daj znać.
menic
SKoro już odświerzylismy temat.....
A co powiecie o własnych sesjach np. takich jak na tym forum questionmark.gif
Zauważyłem że większość dużych skryptów (phpBB, IPB) ma zaimplementowany własny mechanizm zarządzania sesjami opaty o bazy danych. Jestem ciekaw dlaczego jakie są wady i zalety takiego sposobu panowania nad sesjami smile.gif
Ps. jeżeli temat sie przyjmie to dorzucę coś od siebie tylko chce usłyszeć zdanie tych z większym stażem w php biggrin.gif
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.