: Home / PHP / artykuły / Logowanie w PHP - część druga

Warning: file_get_contents(http://graph.facebook.com/http://youthcoders.net/php/artykuly/1034-logowanie-w-php-czesc-druga.html): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden in /var/www/old-yc/plugins/content/addthis.php on line 38
Logowanie w PHP - część druga
Ocena użytkowników: / 17
SłabyŚwietny 
Wpisany przez Tomasz Stasiak   
sobota, 23 kwietnia 2011 22:30

Logowanie w PHP - część druga (wykorzystanie bazy danych)

W tej części postaram się wyjaśnić, jak w prosty sposób stworzyć logowanie na stronie z wykorzystaniem bazy danych MySQL.
Aby tego dokonać będziemy potrzebowali czterech rzeczy - serwera z obsługą php i bazą danych MySQL, oraz trzech plików: db.php, który stworzy nam odpowiednie tabele w bazie danych, login.php w którym umieścimy formularz logowania, oraz secret.php, który będzie odpowiedzialny za sprawdzenie, czy użyszkodnik użytkownik ma dostęp do tajnych zasobów.
Zaczynamy! Tworzymy plik login.php z formularzem logowania o treści identycznej jak w poprzednim przykładzie:
http://ideone.com/4Wmqm
Do połączenia i wykonywania wszystkich operacji na bazie danych wykorzystamy bibliotekę PDO (która powinna być uprzednio zainstalowana na serwerze). Następnie musimy utworzyć plik db.php, w którym umieścimy kod łączący się z bazą danych oraz tworzący w niej odpowiednią tabelę:
http://ideone.com/52z94
Wyjaśnienie: na początku otwieramy sekcję try..catch łapiącą wszelkie wyjątki, które może wyrzucić klasa PDO, wewnątrz try{} kolejno:

  • otwieramy połączenie z bazą danych, gdzie: host_bazy to domena/adres IP serwera bazy danych (jeśli to jest ta sama maszyna, można wpisać localhost); nazwa_bazy - jest to nazwa bazy danych z której będziemy korzystać; user i pass to odpowiednio nazwa użytkownika i jego hasło do bazy danych
  • tworzymy tabelę users zawierającą dane o użytkownikach
  • dodajemy użytkownika admin z takim samym jak poprzednio haszem hasła - czyli utworzonym z 'adminpasswd'
  • Wyświetlamy komunikat

Natomiast w bloku catch łapiemy ewentualne wyjątki oraz wyświetlamy je jeśli wystąpią. W tym wypadku hasło tak samo jak w wypadku logowania z użyciem plików tekstowych jest haszowane. Do wygenerowania haszu z hasła można skorzystać z dostępnych w Internecie narzędzi, np. http://www.insidepro.com/hashes.php. Po utworzeniu odpowiednich tabel można (a nawet dobrze by było) usunąć ten plik, gdyż nie jest on nam do niczego potrzebny. Jeśli to już zostało zrobione, pozostał już tylko 1 plik - secret.php zawierający zasoby, do których dostęp chcemy ograniczyć. Oto, co powinien zawierać:

  • Sprawdzenie, czy użytkownik istnieje w bazie danych i czy podał prawidłowe dane
  • Zapisanie w sesji informacji o tym, że użytkownik ma prawo do dostępu (aby nie trzeba było się logować po każdym odświeżeniu stron
  • Wyświetlenie naszej tajnej treści

Zaczynamy - tworzymy plik secret.php o następującej treści:
http://ideone.com/xDC0d
Teraz wyjaśnienie co się dzieje linijka po linijce: standardowo otwieramy sekcję kodu PHP, w następnej linii rozpoczynamy sesję, po czym sprawdzamy, czy: a) użytkownik wysłał uprzednio jakieś dane przez formularz, b) jest zalogowany. Jeśli żadna z tych sytuacji nie zaistniała - kończymy działanie skryptu (dyrektywa die()). Gdy już wiemy, że użytkownik jest zalogowany/przesłał dane przez formularz otwieramy połączenie z bazą danych - host i nazwa bazy danych, jak i hasło muszą być atkie same jak podczas tworzenia tabeli uzytkowników. Następne 3 linie to tworzenie zapytania wyszukującego użytkownika w bazie danych. :user oraz :passwd oznaczają odpowiednio użytkownika i hasło. Następnie pod wspomniane :user i :passwd podpisujemy odpoiednio nazwę użytkownika, jak i hasz hasła podanego przez użytkownika (podanie danych w ten sposób zamiast bezpośrednio w zapytaniu zabezpiecza nas przed błędami typu SQL Injection; patrz: mój artykuł o bezpieczeństwie danych osobowych w serwisach internetowych, a w szczególności sekcje dot. odzyskiwania haseł i błędów SQL Injection).
Warunek if sprawdza, ile rekordów zwróciło zapytanie; jeśli 1, oznacza to, że użyszkodnik użytkownik z takim hasłem i nazwą został odnaleziony w bazie danych i możemy ustawić wartość $_SESSION['logged_in'] (informującej o zalogowaniu) na true. Ostatnia linia w sekcji try to zamknięcie połączenia pobranych wyników. W sekcji catch, podobnie jak w pliku db.php łapiemy ewentualny wyjątek i wyświetlamy go. Sekcji wewnątrz ciała dokumentu nie będę opisywał, gdyż było to zrobione w poprzedniej części.

 

Jeszcze obiecane porównanie:

    Logowanie z wykorzystaniem plików tekstowych:
        Zalety:
            - Szybkość
            - Niewielkie wymagania wobec serwera
        Wady:
            - Skomplikowane zarządzanie użytkownikami (edycja/usuwanie)
    Logowanie z wykorzystaniem bazy danych:
        Zalety:
            - Łatwość zarządzania użytkownikami
        Wady:
            - Mniejsza szybkość
            - Większe wymagania o serwera

Jak widać, logowanie z użyciem bazy danych ma mniej zalet, lecz ta jedna zwykle przeważa - utrata wydajności nie jest tak duża, a zarządzanie jest wiele prostsze i wydajniejsze.

 

//edit: paczka z kodem do pobrania

 

Komentarze 

 
0 #10 Patryk yarpo Jar 2011-04-25 18:07
Jak najbardziej potwierdzony. Odczyt jest dużo szybszy.

Odczytujesz te dane częściej niż zapisujesz. Wniosek: bd wygrywa :)

Swoją drogą fajnie byłoby podobne testy wykonać np dla SQLite / MySQL / Postgrees

Dodałbym też osobno liczony czas połączeń. Aby móc zobaczyć, czy i w tej kwestii któraś baza [czy też pliki] przoduje. Bardzo fajny artykuł :)
Cytować
 
 
0 #9 Tomasz Stasiak 2011-04-25 17:30
A oto i obiecane testy: http://youthcoders.net/it/dev-zone/1035-wydajnosc-bazy-danych-a-wydajnosc-plikow-tekstowych.html

Dowód przez oczywistość obalony?
Cytować
 
 
0 #8 Patryk yarpo Jar 2011-04-24 23:26
Tomasz, tak się składa, że nawet miałem kiedyś okazję w ramach projektu na studia implementować własny prosty mechanizm bazy danych i nie mówię tu o "bazie danych na plikach tekstowych", a o czymś podobnym do MyIsam.

Jestem zatem świadomy, o czym mówisz :)

Jeśli jednak chodzi o pliki txt, warto pamiętać, że w sytuacji, w której masz więcej niż jeden rekord musisz jakoś danych szukać. Nawet jeśli ich struktura jest płaska w stylu 'login, hasło'. Liniowo musisz przeszukać wszystkie loginy do tego, którego szukasz.

W przypadku baz danych już tak proste zadanie przebiega sprawniej.
Cytować
 
 
0 #7 Tomasz Stasiak 2011-04-24 22:21
Cytat:
Dowód przez oczywistość:
czy ktokolwiek używałby baz danych, gdyby pliki były szybsze? :)

Tak, dlaczego napisałem w ostatnim zdaniu - zarządzanie danymi wewnątrz bazy danych (a szczególnie bardziej skomplikowanymi strukturami) jest o niebo prostsze do realizacji niż zrobienie tego samego na plikach ;] Więc to nie jest aż taka oczywistość. Zastanawiałeś się nad tym od tej strony? :>

BTW zwykle im więcej kodu do wykonania, tym więcej czasu na to potrzeba; taka baza danych w pliku tekstowym to zwykła PHP'owska tablica dwuwymiarowa - macierz (języku skryptowe FTW!), natomiast np. baza MySQL jest trochę bardziej skomplikowaną strukturą, którą software (czyli serwer BD) musi najpierw przetworzyć (choć w sumie dane tego MySQL'a także są przechowywane w jakichś tam plikach o określonej strukturze ;])
Cytować
 
 
0 #6 Patryk yarpo Jar 2011-04-24 20:24
Zależy od tego jak skompliowane dane chcesz odczytywać z "repozytori um doanych" [czy to pliku czy bd].

Z pewnością, jeśli masz wiele rekordów i jest to struktura złożona [a już w ogóle w przypadku relacji] na pewno odczyt z pliku będzie wolniejszy :)

Dowód przez oczywistość:
czy ktokolwiek używałby baz danych, gdyby pliki były szybsze? :)
Cytować
 
 
0 #5 Tomasz Stasiak 2011-04-24 20:20
No nie wiem, czy nietrafiony - jeśli baza danych będzie na tej samej maszynie co skrypt, to nie będzie widać aż takiej różnicy; natomiast jeśli baza będzie na innym serwerze (co się chyba często zdarza), niebędącym bezpośrednio połączonym z serwerem skryptu, to wydajność będzie spadała.
BTW w sumie nigdy tego nie sprawdzałem, więc może spróbuję ;]

ps. miło, że wywołała się dyskusja w komentarzach; mimo, że dwuosobowa to zawsze jakaś ;]
Cytować
 
 
0 #4 Patryk yarpo Jar 2011-04-24 19:48
Możesz zrobić testy porównawcze jak wygląda czasowe wykonanie skryptu dla pojedynczego zapytania:
http://www.yarpo.pl/2010/11/07/mierzenie-czasu-wykonania-skryptu-wlasna-klasa/

Dla pojedynczego może się okazać, że rzeczywiście bd wypada słabiej. Myślę jednak, że przy większej liczbie zapytań korzyści płynące z wykorzystania bd rosłyby.
Cytować
 
 
0 #3 Patryk yarpo Jar 2011-04-24 19:47
Cytat:
Logowanie z wykorzystaniem plików tekstowych:

Zalety:

- Szybkość

- Niewielkie wymagania wobec serwera


No nie wiem... Bazy danych są jednak wydajniejsze od plików tekstowych. Chyba, że chcesz w pliku trzymać baaaaaaaardzo mało danych.

Sądzę, że trochę nietrafiony argument :)
Cytować
 
 
0 #2 Tomasz Stasiak 2011-04-24 17:52
Ok, paczkę za moment dorzucę; jeśli chodzi o nowe materiały, to coś wrzucę w najbliższym czasie (prawdopodobnie związane z kryptografią), ale muszę się zastanowić co dokładnie i jak napisać. Jakieś propozycje (póki mam wolne od szkoły ;])?

ps. kod wrzuciłem od razu na zewnętrzny serwis, po uprzednich problemach w części pierwszej...
Cytować
 
 
0 #1 Patryk yarpo Jar 2011-04-24 16:59
Proponowałbym stworzenie paczki zip z kodem gotowym do odpalenia :)

Miło patrzeć jak pojawiają się nowe materiały! <czeka na kolejne>
Cytować
 

Dodaj komentarz


Kod antysapmowy
Odśwież