Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [skrypt] Własny mechanizm Sesji & sterownik bazy danych
Forum PHP.pl > Inne > Oceny
Kuzry
Witam smile.gif Są to moje 2 pierwsze skrypty oparte o OOP więc proszę o wyrozumiałość winksmiley.jpg Chciałbym żebyście ocienili jak wam się podobają skrypty i w razie co wychwycili jakieś błędy. Czy sesja jest wystarczająco bezpieczna i czy losowany identyfikator sesji będzie unikalny. Z góry dzięki za wszystkie ocenki winksmiley.jpg


Najpierw kod do utworzenia bazy danych:
  1. CREATE TABLE sesja(
  2. id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
  3. identyfikatorSesji CHAR(32) NOT NULL,
  4. zalogowany CHAR(5) NOT NULL,
  5. idUzytkownika INTEGER NOT NULL,
  6. ostatniaReakcja BIGINT(15) NOT NULL,
  7. utworzono BIGINT(15) NOT NULL,
  8. przegladarka CHAR(255) NOT NULL
  9. );
  10.  
  11. CREATE TABLE zmiennesesji(
  12. identyfikatorSesji CHAR(32) NOT NULL,
  13. nazwaZmiennej CHAR(64) NOT NULL,
  14. wartoscZmiennej TEXT NOT NULL
  15. )


Kod klasy Sesja
CODE
class Sesja {
private $id; //id sesji w bazie danych
private $identyfikatorSesji; //identyfikator Sesji pobierany z Cookie
private $zalogowany;
private $idUzytkownika;
private $przegladarka;
private $czasTrwaniaSesji = 600;
private $czasZyciaSesji = 3600;

private $uchwytBazy;



public function __construct(){
$this->uchwytBazy = new BazaDanych();

// sprawdzenie czy istnieje cookie sesji
if(! isset($_COOKIE["SESSIONID"])){
$id = $this->losujId();
$this->identyfikatorSesji = $id;
setcookie("SESSIONID", $id, time() + $this->czasZyciaSesji);
unset($id);
} else {
$this->identyfikatorSesji = $_COOKIE["SESSIONID"];
}

//start sesji i czyszczenie niepotrzebnych wpisów w bazie
$this->session_open();
$this->wyczyscStareSesje();
}



// funkcja tworzaca sesje
private function session_open(){
$this->przegladarka = $_SERVER['HTTP_USER_AGENT'];

$data = date("YmdGis");
$dane = $this->uchwytBazy->select("SELECT id FROM sesja WHERE identyfikatorSesji = '$this->identyfikatorSesji'
AND (('".$data."' - utworzono) < '$this->czasZyciaSesji seconds')
AND przegladarka = '$this->przegladarka'
AND (('".$data."' - ostatniaReakcja) <= '$this->czasTrwaniaSesji seconds'
OR ostatniareakcja IS NULL)");

if($dane['liczbaWierszy']==0){
$this->uchwytBazy->insert('sesja', array('identyfikatorSesji'=>$this->identyfikatorSesji, 'zalogowany'=>'false', 'idUzytkownika'=>0, 'ostatniaReakcja'=>$data, 'utworzono'=>$data, 'przegladarka'=>$this->przegladarka));
$dane = $this->uchwytBazy->select("SELECT id FROM sesja WHERE identyfikatorSesji = '$this->identyfikatorSesji'");
$this->id = $dane['id'];
} else {
$this->uchwytBazy->update('sesja', array('ostatniaReakcja'=>$data), array('identyfikatorSesji'=>$this->identyfikatorSesji));
}
unset($data);
}


// funkcja czyszczaca niepotrzebne wpisy w bazie
private function wyczyscStareSesje(){
$data = date("YmdGis");
$rezultat = mysql_query("DELETE FROM sesja WHERE (('$data' - ostatniaReakcja) > '$this->czasTrwaniaSesji') OR (('$data' - utworzono) > '$this->czasZyciaSesji')");

if(mysql_affected_rows($this->uchwytBazy->uchwytBazy)>0){
$this->uchwytBazy->delete('zmiennesesji', array('identyfikatorSesji'=>$this->identyfikatorSesji));
}
unset($data);
}


// funkcja pobiera zmienne sesyjne z bazy danych
public function __get($nazwa){
$dane = $this->uchwytBazy->select("SELECT wartoscZmiennej FROM zmiennesesji WHERE identyfikatorSesji = '$this->identyfikatorSesji' AND nazwaZmiennej = '$nazwa'");

if($dane['liczbaWierszy']>0){
return unserialize($dane['wartoscZmiennej']);
} else {
return false;
}
}


// funkcja zapisuje zmienne sesji w bazie danych
public function __set($nazwa, $wartosc){
$wartosc = serialize($wartosc);
$dane = $this->uchwytBazy->select("SELECT wartoscZmiennej FROM zmiennesesji WHERE identyfikatorSesji = '$this->identyfikatorSesji' AND nazwaZmiennej = '$nazwa'");

if($dane['liczbaWierszy']==0){
$this->uchwytBazy->insert('zmiennesesji', array('identyfikatorSesji'=>$this->identyfikatorSesji, 'nazwaZmiennej'=>$nazwa, 'wartoscZmiennej'=>$wartosc));
} else {
$this->uchwytBazy->update('zmiennesesji', array('wartoscZmiennej'=>$wartosc), array('identyfikatorSesji'=>$this->identyfikatorSesji, 'nazwaZmiennej'=>$nazwa));
}
}



// funkcja losująca identyfikator sesji
private function losujId(){
$numer = rand(1, 10000000000000000) + mktime();
return md5($numer);
}
}




Sterownik bazy danych:
CODE

class BazaDanych {
public $uchwytBazy;

// nawiązuje połączenie z baządanych
public function __construct(){
$this->uchwytBazy = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
if(! is_resource($this->uchwytBazy)){
die('Niemożna nawiązać połączenia z bazą danych');
exit();
}

mysql_select_db(DB_NAME);
}



// konczy połączenie z bazą danych
public function __destruct(){
if (is_resource($this->uchwytBazy)){
@mysql_close($this->uchwytBazy);
}
}


// funkcja pobierajaca wiersze z bazy
public function select($sql){
$rezultat = @mysql_query($sql);

if($rezultat==false){
echo mysql_error();
die('<br />Błąd podczas wysyłania zapytania');
exit();
}

$zwracanyWiersz = mysql_fetch_array($rezultat);

$liczbaWierszy = mysql_num_rows($rezultat);

$zwracanyWiersz['liczbaWierszy'] = $liczbaWierszy;

return $zwracanyWiersz;
}


// funkcja dodajaca wiersze do bazy
public function insert($nazwaTabeli, $tablicaDanych){

$klucze = array_keys($tablicaDanych);
$wartosci = array_values($tablicaDanych);

foreach ($wartosci as $w){
if(! is_numeric($w)){
$w = "'".mysql_escape_string($w)."'";
}
$tablicaWartosci[] = $w;
}

$sql = "INSERT INTO $nazwaTabeli (";
$sql .= join(', ',$klucze);
$sql .= ') VALUES(';
$sql .= join(', ', $tablicaWartosci);
$sql .= ')';

$rezultat = mysql_query($sql);

if($rezultat==false){
die('<br />Błąd przy wysyłaniu zapytania do bazy1111');
exit();
}

return true;
}


// funkcja kasujaca wiersze w bazie
public function delete($nazwaTabeli, $where){
$tablicaWhere = array();

foreach ($where as $klucz => $wartosc){
if(! is_numeric($wartosc)){
$wartosc = "'".mysql_escape_string($wartosc)."'";
}
$tablicaWhere[] = "$klucz = $wartosc";
}

$sql = "DELETE FROM $nazwaTabeli WHERE ".join(' AND', $tablicaWhere);

$rezultat = mysql_query($sql, $this->uchwytBazy);
if($rezultat==false){
die('<br />Błąd przy wysyłaniu zapytania do bazy22222');
exit();
}

return mysql_affected_rows($this->uchwytBazy);
}


// funkcja aktualizująca wiersze w bazie
public function update($nazwaTabeli, $tablicaWartosci, $where){
$tablicaUpdate = array();

foreach ($tablicaWartosci as $klucz => $wartosc){
if(! is_numeric($wartosc)){
$wartosc = "'".mysql_escape_string($wartosc)."'";
}
$tablicaUpdate[] = "$klucz = $wartosc";
}

$tablicaWhere = array();
foreach ($where as $klucz => $wartosc){
if(! is_numeric($wartosc)){
$wartosc = "'".mysql_escape_string($wartosc)."'";
}

$tablicaWhere[] = "$klucz = $wartosc";

}

$sql = "UPDATE $nazwaTabeli SET ";
$sql .= join(' ,', $tablicaUpdate);
$sql .= " WHERE ".join(' AND ', $tablicaWhere);

$rezultat = mysql_query($sql);
if($rezultat==false){
die('<br />Błąd przy wysyłaniu zapytania do bazy1111');
exit();
}

return true;
}
}
sniezny_wilk
Odnośnie Twojego pytania o unikalność: istnieje małe prawdopodobieństwo, że się klucz powtórzy

  1. <?php
  2. private function losujId(){
  3. $numer = rand(1, 10000000000000000) + mktime();
  4. return md5($numer);
  5. }
  6. ?>


zupełnie bezsensu, wystarczy w zupełności microtime" title="Zobacz w manualu PHP" target="_manual, reszty nie przeglądałem bo odkrywanie ameryki na nowo to nic ciekawego.

EDIT, literóweczka w Twoim kodzie: "die('<br />Błąd przy wysyłaniu zapytania do bazy1111');" winksmiley.jpg

Nie widzę zabezpieczenia przez SQL injection.
kwiateusz
jak juz uzywasz php5 to moglbys mysqli i jego bind'ow itp smile.gif oraz rzucac wyjatkami zamiast die...
Babcia@Stefa
Kodu jakoś nie chce mi się całego czytać ale z tego co widzę to żucają się w oczy polskie nazwy zmiennych i funkcji (to chyba źle nie jest - ale lepiej wyglądają angielskie winksmiley.jpg - dlatego też każdy może odczytać kod, nie tylko polak), no i te die().

Co do tych die, to zastąp je wyjątkami:

w klasie:

  1. <?php
  2. throw new Exception('ClassName :: Function: Error name', 1); // drugi parametr to numer błędu, pierwszy to wiadomość ;)
  3. ?>


w użyciu przy tworzeniu obiektu (np. poza klasami):

  1. <?php
  2. try {
  3.  $obiekt = new DataBaseController();
  4.  $obiekt -> Connect(..., ..., ..., ...)
  5. }
  6.  
  7. catch (Exception $e)
  8. {
  9. die('Wystąpił błąd "' .$e->GetMessage(). '" o kodzie błędu "' .$e->GetCode(). '".');
  10. }
  11. ?>


@edit
Używaj tagów [ php ] { kod } [ / php] smile.gif

@edit
Skąd bierzesz te stałe:
  1. <?php
  2. $this->uchwytBazy = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
  3. ?>


Jeżeli przy tworzeniu obiektu nie łączysz się z DB, nie pobierasz ich, nie includujesz w funkcji __construct() pliku?

@edit
Chyba że stałe mają zasięg aż do klas (nigdy tego nie sprawdzałem winksmiley.jpg)

Dziękuję, Babcia@Stefa
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.