DZWONEK

Są tacy, którzy czytają tę wiadomość przed wami.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz przeczytać The Bell
Bez spamu

Technologia sesji w PHPw prosty sposób przechowywanie informacji dla pojedynczego użytkownika serwisu. Na przykład: produkty dodane do koszyka sklepu, ustawienia powiadomień itp. Przy pierwszym żądaniu witryny skierowanym do serwera w przeglądarce zapisywany jest unikalny plik cookie identyfikator sesji użytkownik. Identyfikator lub powiązanie identyfikatora z adresem IP następnie identyfikuje użytkownika. Może to służyć do utrwalania stanu między żądaniami stron. Identyfikatory sesji są zwykle wysyłane do przeglądarki za pośrednictwem plików cookie sesji i służą do pobierania dostępnych danych sesji.

Sesje używają prosta technologia: PHP pobierze istniejące dane sesji przy użyciu przekazanego identyfikatora (zwykle z sesji ciastko) lub jeśli nic nie zostało przesłane, zostanie utworzona nowa sesja. Po rozpoczęciu sesji PHP zapełni superglobalną $ _SESSION informacjami o sesji. Kiedy PHP kończy pracę, automatycznie serializuje zawartość superglobalnej $ _SESSION i wysyła ją do przechowywania, używając procedury obsługi sesji do zapisania sesji.

PHP domyślnie używa wewnętrznego modułu obsługi akta aby zapisać sesje, który jest ustawiony w zmiennej session.save_handler INI. Ta procedura obsługi zapisuje dane na serwerze w katalogu określonym w dyrektywie konfiguracyjnej session.save_path.

Najprostszy przykład wykorzystania sesji, na przykład wyświetlenie liczby odwiedzin strony dla każdego użytkownika:

Jak jest możliwe blokowanie sesji?

Na stronie php w sekcji opisu sesji (http://php.net/manual/ru/session.examples.basic.php) znajduje się notatka:

Sesje korzystające z plików (domyślnie w PHP), blokuj plik sesji natychmiast po otwarciu sesji za pomocą funkcji session_start () lub pośrednio podczas określania session.auto_start. Po zablokowaniu żaden inny skrypt nie może uzyskać dostępu do tego samego pliku sesji, dopóki nie zostanie on zamknięty ani po zakończeniu skryptu, ani po wywołaniu funkcji session_write_close ().

Najprawdopodobniej stanie się to problemem dla witryn, które aktywnie używają AJAX i wykonaj wiele jednoczesnych żądań. Najłatwiejszym sposobem rozwiązania tego problemu jest wywołanie funkcji session_write_close (), gdy tylko zostaną wprowadzone wszystkie wymagane zmiany w sesji, najlepiej bliżej początku skryptu. Możesz także użyć innego mechanizmu sesji, który obsługuje współbieżność.

Ostatnio problem blokowania sesji stał się coraz częstszy. Wynika to częściowo z komplikacji witryn i konieczności wykonywania większej liczby obliczeń po stronie serwera, a także z większej dystrybucji AJAX... Niestety logika aplikacji, zwłaszcza jeśli jest złożona, nie zawsze skutecznie ogranicza czas blokowania procesów konkurujących o sesję. Sytuację pogarsza fakt, że 3-5 takich klientów jest w stanie szybko zapchać pracowników PHP zamrożonymi i bezczynnymi procesami, w wyniku czego strona zacznie wydawać Błąd 5XX .

Najprostszy przykład blokowania sesji:

// tylko dla jednego skryptu ?>

Jeśli otworzysz ten plik najpierw na pierwszej karcie, a następnie na drugiej, druga karta będzie czekać, aż pierwsza zostanie zakończona. Oznacza to, że w rzeczywistości druga karta będzie czekać, aż pierwsza zwolni plik sesji (co w tym konkretnym przypadku zajmuje 30 sekund). Ten problem dobrze opisane na firmowym blogu 1C-Bitrix na Habrahabr.

Jakie są możliwości rozwiązania tego problemu

Do przechowywania sesji można używać baz danych, takich jak MySQL lub PostgreSQL (co nie jest do końca poprawne, biorąc pod uwagę możliwości większości baz danych i możliwą szybkość pracy w to zadanie), Memcached (nie gwarantuje przechowywania sesji, może zostać usunięta) i Redisw co wierzymy optymalne przechowywanie... Pod względem szybkości nie ustępuje Memcached, ale jednocześnie może zagwarantować bezpieczeństwo danych.

I najważniejsza zaleta Redis - podczas przechowywania w nim sesji nie są one blokowane.

W naszym panelu sterowania () możesz włączyć przechowywanie sesji w Redis dla wszystkich witryn na swoim koncie. Aby to zrobić, przejdź do sekcji „ Strony internetowe", a następnie zaznacz pole -" Przechowuj sesje wszystkich witryn w Redis".

Dodatkowe materiały

Sekcje

SSH

FTP

Aplikacje internetowe

  • Omówienie instalacji aplikacji (środowisko wirtualne Docker)

Diagnozowanie problemów

Domeny

  • Anulowanie domeny w strefie .RU / .РФ, której Beget jest rejestratorem
  • Przeniesienie praw administracyjnych do domeny .RU / .РФ / .SU i stref międzynarodowych (Zmiana administratora domeny)

Witaj droga społeczność.

Przede wszystkim chciałbym podziękować za bardzo przydatne źródło informacji. Znalazłem tutaj wiele ciekawych pomysłów i praktycznych porad.

Celem tego artykułu jest zwrócenie uwagi na pułapki związane z używaniem sesji w PHP. Oczywiście istnieje dokumentacja PHP i wiele przykładów, a ten artykuł nie jest przeznaczony kompletny przewodnik... Ma na celu ujawnienie niektórych niuansów pracy z sesjami i ochronę programistów przed niepotrzebną stratą czasu.

Najczęstszym przypadkiem użycia sesji jest oczywiście autoryzacja użytkownika. Zacznijmy od najbardziej podstawowej implementacji, abyśmy mogli ją konsekwentnie rozwijać w miarę pojawiania się nowych wyzwań.

(Aby zaoszczędzić miejsce i czas, ograniczymy się do przykładów tylko przez funkcje do pracy z sesjami, zamiast budować tutaj pełnoprawną aplikację testową z piękną hierarchią klas, wyczerpującą obsługą błędów i innymi poprawnymi rzeczami).

Function startSession () (// Jeśli sesja została już rozpoczęta, zatrzymaj wykonywanie i zwróć TRUE // (parametr session.auto_start w pliku ustawień php.ini musi być wyłączony - wartość domyślna) if (session_id ()) return true; else return session_start (); // Uwaga: przed wersją 5.3.0 funkcja session_start () zwracała TRUE nawet w przypadku błędu. // Jeśli używasz wersji poniżej 5.3.0, wykonaj dodatkową walidację session_id () // po wywołaniu funkcji session_start ()) zniszczSession () (if (session_id ()) (// Jeśli istnieje aktywna sesja, usuń pliki cookie sesji, setcookie (session_name (), session_id (), time () - 60 * 60 * 24); // i zniszcz sesję session_unset ( ); session_destroy ();))

Uwaga: Zakłada się, że czytelnik ma podstawową wiedzę o sesjach PHP, więc nie będziemy tutaj omawiać zasady działania funkcji session_start () i session_destroy (). Zadania związane z układem formularza logowania i uwierzytelnianiem użytkownika nie są związane z tematyką artykułu, więc je również pominiemy. Przypomnę tylko, że aby zidentyfikować użytkownika w każdym kolejnym żądaniu, w momencie udanego logowania, musimy zapisać identyfikator użytkownika w zmiennej sesyjnej (np. Z nazwą userid), która będzie dostępna we wszystkich kolejnych żądaniach w czasie trwania sesji. Konieczne jest również zaimplementowanie przetwarzania wyniku naszej funkcji startSession (). Jeśli funkcja zwraca FALSE, wyświetl formularz logowania w przeglądarce. Jeśli funkcja zwraca TRUE, a zmienna sesyjna zawierająca identyfikator uprawnionego użytkownika (w naszym przypadku identyfikator użytkownika) istnieje - wyświetl stronę autoryzowanego użytkownika (więcej szczegółów dotyczących obsługi błędów znajduje się w dodatku z dnia 2013-06-07 w sekcji o zmiennych sesyjnych).

Jak dotąd wszystko jest jasne. Pytania zaczynają się, gdy wymagana jest kontrola bezczynności użytkownika (przekroczenie limitu czasu sesji), umożliwienie kilku użytkownikom jednoczesnej pracy w jednej przeglądarce, a także ochrona sesji przed nieautoryzowanym użyciem. Zostanie to omówione poniżej.

Kontrolowanie braku aktywności użytkowników za pomocą wbudowanych narzędzi PHP

Pierwszym pytaniem, które często pojawia się wśród twórców wszelkiego rodzaju konsol dla użytkowników, jest automatyczne zakończenie sesji w przypadku braku aktywności ze strony użytkownika. Nie może być łatwiejsze niż korzystanie z wbudowanych funkcji PHP. (Ta opcja nie jest szczególnie niezawodna i elastyczna, ale rozważmy ją dla kompletności).

Function startSession () (// Limit czasu braku aktywności użytkownika (w sekundach) $ sessionLifetime \u003d 300; if (session_id ()) return true; // Ustaw czas życia pliku cookie ini_set ("session.cookie_lifetime", $ sessionLifetime); // Jeśli ustawiono limit czasu braku aktywności użytkownika, ustaw czas życia sesji na serwerze // Uwaga: W przypadku serwera produkcyjnego zaleca się ustawienie tych parametrów w pliku php.ini if \u200b\u200b($ sessionLifetime) ini_set ("session.gc_maxlifetime", $ sessionLifetime); if (session_start ( )) (setcookie (session_name (), session_id (), time () + $ sessionLifetime); return true;) else return false;)

Kilka wyjaśnień. Jak wiesz, PHP określa, która sesja ma się rozpocząć na podstawie nazwy pliku cookie przekazanego przez przeglądarkę w nagłówku żądania. Przeglądarka z kolei otrzymuje ten plik cookie z serwera, na którym umieszcza go funkcja session_start (). Jeśli plik cookie wygasł w przeglądarce, nie zostanie przesłany w żądaniu, co oznacza, że \u200b\u200bPHP nie będzie w stanie określić, którą sesję rozpocząć, i uzna to za utworzenie nowej sesji. Parametr ustawień PHP session.gc_maxlifetime, który jest równy naszemu limitowi czasu braku aktywności użytkownika, ustawia czas życia sesji PHP i jest kontrolowany przez serwer. Kontrola czasu trwania sesji działa w następujący sposób (tutaj rozważamy przykład przechowywania sesji w plikach tymczasowych jako najpopularniejszą i domyślną wersję w PHP).

W czasie tworzenia nowej sesji w katalogu ustawionym jako katalog do przechowywania sesji w parametrze ustawień PHP session.save_path tworzony jest plik o nazwie sess_. gdzie - identyfikator sesji. Ponadto w każdym żądaniu, w momencie rozpoczynania istniejącej sesji, PHP aktualizuje czas modyfikacji tego pliku. W ten sposób w każdym kolejnym żądaniu PHP, na podstawie różnicy między aktualnym czasem a czasem ostatniej modyfikacji pliku sesji, może określić, czy sesja jest aktywna, czy też jej czas życia już wygasł. (Mechanizm usuwania starych plików sesji jest omówiony bardziej szczegółowo w następnej sekcji).

Uwaga: Należy tutaj zauważyć, że parametr session.gc_maxlifetime wpływa na wszystkie sesje na tym samym serwerze (a dokładniej w ramach tego samego głównego procesu PHP). W praktyce oznacza to, że jeśli na serwerze działa kilka witryn, a każda z nich ma swój własny limit czasu nieaktywności użytkowników, to ustawienie tego parametru na jednej z witryn doprowadzi do jej instalacji dla innych witryn. To samo dotyczy hostingu współdzielonego. Aby uniknąć takiej sytuacji, dla każdej lokacji na jednym serwerze używane są oddzielne katalogi sesji. Ustawienie ścieżki do katalogu sesji odbywa się za pomocą parametru session.save_path w pliku ustawień php.ini lub przez wywołanie funkcji ini_set (). Następnie sesje każdej witryny będą przechowywane w oddzielnych katalogach, a parametr session.gc_maxlifetime ustawiony na jednej z witryn będzie działał tylko w jej sesji. Nie będziemy omawiać tego przypadku szczegółowo, zwłaszcza, że \u200b\u200bmamy bardziej elastyczną opcję kontrolowania braku aktywności użytkownika.

Kontrolowanie braku aktywności użytkownika za pomocą zmiennych sesji

Wydawałoby się, że poprzednia opcja, mimo całej swojej prostoty (zaledwie kilka dodatkowych linii kodu), daje wszystko, czego potrzebujemy. Ale co, jeśli nie każde żądanie można traktować jako wynik aktywności użytkownika? Na przykład strona ma licznik czasu, który okresowo wysyła żądanie AJAX w celu otrzymania aktualizacji z serwera. Żądania takiego nie można traktować jako aktywności użytkownika, co oznacza, że \u200b\u200bautomatyczne przedłużenie czasu trwania sesji nie jest w tym przypadku poprawne. Wiemy jednak, że PHP automatycznie aktualizuje czas modyfikacji pliku sesji przy każdym wywołaniu funkcji session_start (), co oznacza, że \u200b\u200bkażde żądanie doprowadzi do wydłużenia czasu trwania sesji, a limit czasu braku aktywności użytkownika nigdy nie nastąpi. Ponadto ostatnia notatka z poprzedniej sekcji dotycząca zawiłości parametru session.gc_maxlifetime może wydawać się zbyt zagmatwana i skomplikowana do zaimplementowania.

Aby rozwiązać ten problem zrezygnujemy z korzystania z wbudowanych mechanizmów PHP i wprowadzimy kilka nowych zmiennych sesyjnych, które pozwolą nam samodzielnie kontrolować czas bezczynności użytkowników.

Funkcja startSession ($ isUserActivity \u003d true) ($ sessionLifetime \u003d 300; if (session_id ()) return true; // Ustaw czas życia ciasteczka do zamknięcia przeglądarki (będziemy kontrolować wszystko po stronie serwera) ini_set ("session.cookie_lifetime", 0) ; if (! session_start ()) return false; $ t \u003d time (); if ($ sessionLifetime) (// Jeśli ustawiony jest limit czasu bezczynności użytkownika, // sprawdź czas, który upłynął od ostatniej aktywności użytkownika // (czas ostatniego żądania kiedy zmienna sesyjna lastactivity została zaktualizowana) if (isset ($ _ SESSION ["lastactivity"]) && $ t - $ _ SESSION ["lastactivity"]\u003e \u003d $ sessionLifetime) (// Jeśli czas, jaki upłynął od ostatniej aktywności użytkownika / / more inactivity timeout, oznacza to, że sesja wygasła i musisz zakończyć sesję zniszczSession (); return false;) else (// Jeśli limit czasu jeszcze nie nastąpił, // a jeśli żądanie nadeszło w wyniku działania użytkownika, // zaktualizuj zmienną lastactivity o wartość bieżącej vr emeny, // wydłużając w ten sposób czas sesji o kolejne sessionLifetime sekundy if ($ isUserActivity) $ _SESSION ["lastactivity"] \u003d $ t; )) return true; )

Podsumujmy. W każdym żądaniu sprawdzamy, czy upłynął limit czasu od ostatniej aktywności użytkownika do bieżącego momentu, a jeśli został osiągnięty, niszczymy sesję i przerywamy wykonywanie funkcji, zwracając FALSE. Jeśli limit czasu nie został osiągnięty, a do funkcji jest przekazywany parametr $ isUserActivity o wartości TRUE, aktualizujemy czas ostatniej aktywności użytkownika. Wszystko, co musimy zrobić, to określić w skrypcie wywołującym, czy żądanie jest wynikiem aktywności użytkownika, a jeśli nie, wywołać funkcję startSession z wartością parametru $ isUserActivity równą FALSE.

Aktualizacja z dnia 2013-06-07
Przetwarzanie wyniku funkcji sessionStart ()

W komentarzach zauważyli, że zwrócenie FAŁSZ nie daje pełnego zrozumienia przyczyny błędu i jest to absolutna prawda. Nie publikowałem tutaj szczegółowej obsługi błędów (objętość artykułu i tak nie jest mała), ponieważ nie dotyczy to bezpośrednio tematu artykułu. Ale biorąc pod uwagę komentarze, wyjaśnię.

Jak widać, funkcja sessionStart może zwrócić FALSE w dwóch przypadkach. Albo sesja nie mogła zostać uruchomiona z powodu niektórych błędy wewnętrzne serwer (na przykład nieprawidłowe ustawienia sesji w php.ini) lub sesja wygasła. W pierwszym przypadku musimy przekierować użytkownika na stronę z błędem informującym o problemach na serwerze oraz formą kontaktu z pomocą techniczną. W drugim przypadku musimy przenieść użytkownika do formularza logowania i wyświetlić w nim odpowiedni komunikat, że sesja wygasła. Aby to zrobić, musimy wprowadzić kody błędów i zwrócić odpowiedni kod zamiast FALSE, sprawdzić go w metodzie wywołującej i odpowiednio postępować.

Teraz, nawet jeśli sesja na serwerze nadal istnieje, zostanie zniszczona przy pierwszym dostępie do niej, jeśli upłynął limit czasu braku aktywności użytkownika. Dzieje się tak niezależnie od tego, jaki czas trwania sesji jest ustawiony w globalnych ustawieniach PHP.

Uwaga: Co się stanie, jeśli przeglądarka zostanie zamknięta, a plik cookie z nazwą sesji zostanie automatycznie zniszczony? Żądanie do serwera przy następnym otwarciu przeglądarki nie będzie zawierało sesyjnych plików cookie, a serwer nie będzie mógł otworzyć sesji i sprawdzić czasu bezczynności użytkownika. Dla nas jest to równoznaczne z utworzeniem nowej sesji i nie wpływa w żaden sposób na funkcjonalność ani bezpieczeństwo. Powstaje jednak uczciwe pytanie - kto w takim razie zniszczy starą sesję, jeśli zniszczyliśmy ją do teraz po wygaśnięciu limitu czasu? A może zawiesi się teraz w katalogu sesji na zawsze? Do czyszczenia starych sesji PHP ma mechanizm zwany zbieraniem śmieci. Rozpoczyna się w momencie następnego żądania do serwera i czyści wszystkie stare sesje na podstawie daty ostatnia zmiana pliki sesji. Jednak mechanizm czyszczenia pamięci nie jest uruchamiany przy każdym żądaniu skierowanym do serwera. Częstotliwość (a raczej prawdopodobieństwo) uruchomienia jest określana przez dwa parametry ustawień session.gc_probability i session.gc_divisor. Wynik podzielenia pierwszego parametru przez drugi to prawdopodobieństwo uruchomienia mechanizmu czyszczenia pamięci. Dlatego, aby mechanizm czyszczenia sesji uruchamiał się przy każdym żądaniu skierowanym do serwera, parametry te muszą mieć równe wartości, na przykład „1”. Takie podejście zapewnia, że \u200b\u200bkatalog sesji jest czysty, ale oczywiście jest zbyt drogi dla serwera. Dlatego w systemach produkcyjnych session.gc_divisor jest domyślnie ustawione na 1000, co oznacza, że \u200b\u200bsilnik czyszczenia pamięci zostanie uruchomiony z prawdopodobieństwem 1/1000. Jeśli poeksperymentujesz z tymi ustawieniami w pliku php.ini, zauważysz, że w powyższym przypadku, gdy przeglądarka zamknie się i wyczyści wszystkie swoje pliki cookie, w katalogu sesji nadal będą znajdować się stare sesje. Ale to nie powinno cię martwić, ponieważ jak już wspomniano, nie wpływa to w żaden sposób na bezpieczeństwo naszego mechanizmu.

Aktualizacja z dnia 2013-06-07

Zapobieganie zawieszaniu się skryptów z powodu blokowania pliku sesji

W komentarzach poruszyli kwestię zawieszania się jednocześnie uruchomionych skryptów z powodu blokowania pliku sesyjnego (jako najjaśniejsza opcja - długa ankieta).

Na początek zauważam, że ten problem nie zależy bezpośrednio od obciążenia serwera ani liczby użytkowników. Oczywiście im więcej żądań, tym wolniej uruchamiają się skrypty. Ale to jest zależność pośrednia. Problem pojawia się tylko w ramach tej samej sesji, gdy serwer otrzymuje kilka żądań w imieniu jednego użytkownika (np. Jedno z nich to długie odpytywanie, a reszta to zwykłe żądania). Każde żądanie próbuje uzyskać dostęp do tego samego pliku sesji, a jeśli poprzednie żądanie nie odblokowało pliku, następne żądanie zawiesi się w oczekiwaniu.

Aby ograniczyć do minimum blokowanie plików sesji, zdecydowanie zaleca się zamknięcie sesji przez wywołanie funkcji session_write_close () natychmiast po wykonaniu wszystkich akcji ze zmiennymi sesji. W praktyce oznacza to, że nie należy przechowywać wszystkiego w zmiennych sesyjnych i odnosić się do nich podczas wykonywania skryptu. A jeśli chcesz przechowywać jakieś dane robocze w zmiennych sesyjnych, przeczytaj je natychmiast na początku sesji, zapisz do zmiennych lokalnych do późniejszego wykorzystania i zamknij sesję (co oznacza zamknięcie sesji za pomocą funkcji session_write_close, a nie zniszczenie jej za pomocą session_destroy).

W naszym przykładzie oznacza to, że zaraz po otwarciu sesji, sprawdzeniu jej czasu życia i istnienia autoryzowanego użytkownika, musimy odczytać i zapisać wszystkie dodatkowe zmienne sesyjne niezbędne dla aplikacji (jeśli takie istnieją), następnie zamknąć sesję wywołując session_write_close () i kontynuować wykonanie skryptu, czy to długa ankieta, czy zwykłe żądanie.

Ochrona sesji przed nieautoryzowanym użyciem

Wyobraźmy sobie sytuację. Jeden z Twoich użytkowników przechwytuje trojana, który okrada plik cookie przeglądarki (w którym przechowywana jest nasza sesja) i wysyła go na określony adres e-mail. Atakujący otrzymuje plik cookie i wykorzystuje go do sfałszowania żądania w imieniu naszego autoryzowanego użytkownika. Serwer pomyślnie akceptuje i przetwarza to żądanie tak, jakby pochodziło od autoryzowanego użytkownika. Jeśli nie zaimplementowano dodatkowa weryfikacja Adresy IP, taki atak doprowadzi do udanego włamania się na konto użytkownika ze wszystkimi wynikającymi z tego konsekwencjami.

Dlaczego jest to możliwe? Oczywiście, ponieważ nazwa i identyfikator sesji są zawsze takie same przez cały czas trwania sesji, a jeśli otrzymasz te dane, możesz swobodnie wysyłać żądania w imieniu innego użytkownika (oczywiście w czasie trwania tej sesji). Być może nie jest to najczęstszy rodzaj ataku, ale w teorii wszystko wydaje się całkiem wykonalne, zwłaszcza biorąc pod uwagę, że taki trojan nie potrzebuje nawet uprawnień administratora, aby ukraść pliki cookie przeglądarki użytkownika.

Jak możesz się bronić przed tego typu atakami? Ponownie, oczywiście, ograniczając czas życia identyfikatora sesji i okresowo zmieniając identyfikator w ramach jednej sesji. Możemy również zmienić nazwę sesji, całkowicie usuwając starą i tworząc nową sesję, kopiując do niej wszystkie zmienne sesji ze starej. Nie wpływa to jednak na istotę podejścia, dlatego dla uproszczenia ograniczymy się tylko do identyfikatora sesji.

Oczywiste jest, że im krótszy okres istnienia identyfikatora sesji, tym mniej czasu osoba atakująca będzie musiała uzyskać i wykorzystać pliki cookie do sfałszowania żądania użytkownika. W idealnym przypadku dla każdego żądania powinien być używany nowy identyfikator, aby zminimalizować możliwość korzystania z sesji innej osoby. Ale rozważymy ogólny przypadek, w którym czas odświeżania identyfikatora sesji jest ustawiany arbitralnie.

(Pomińmy część kodu, która została już omówiona).

Function startSession ($ isUserActivity \u003d true) (// Okres istnienia identyfikatora sesji $ idLifetime \u003d 60; ... if ($ idLifetime) (// Jeśli ustawiono okres istnienia identyfikatora sesji, // sprawdź czas, jaki upłynął od utworzenia sesji lub ostatnią regeneracja // (czas ostatniego żądania po zaktualizowaniu zmiennej sesji starttime) if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]\u003e \u003d $ idLifetime) (// Time identyfikator sesji wygasł // Wygeneruj nowy identyfikator session_regenerate_id (true); $ _SESSION ["starttime"] \u003d $ t;)) else (// Otrzymamy tutaj, jeśli sesja została właśnie utworzona // Ustaw czas generowania identyfikatora sesji na bieżący czas $ _SESSION ["starttime"] \u003d $ t;)) return true;)

Tak więc podczas tworzenia nowej sesji (co następuje po pomyślnym zalogowaniu użytkownika), ustawiamy zmienną sesyjną starttime, która przechowuje dla nas czas ostatniej generacji ID sesji, na wartość równą aktualnemu czasowi serwera. Ponadto w każdym żądaniu sprawdzamy, czy od ostatniej generacji identyfikatora minęło wystarczająco dużo czasu (idLifetime), a jeśli tak, generujemy nowy. Tak więc, jeśli w określonym czasie trwania identyfikatora atakujący, który otrzymał plik cookie autoryzowanego użytkownika, nie zdoła go wykorzystać, fałszywe żądanie zostanie uznane przez serwer za nieautoryzowane, a atakujący zostanie przeniesiony na stronę logowania.

Uwaga: Nowy identyfikator sesji dostaje się do pliku cookie przeglądarki, gdy wywoływana jest funkcja session_regenerate_id (), która wysyła nowy plik cookie, podobny do funkcji session_start (), więc nie musimy sami aktualizować plików cookie.

Jeśli chcemy maksymalnie zabezpieczyć nasze sesje, wystarczy ustawić czas życia identyfikatora na jeden, a nawet umieścić funkcję session_regenerate_id () poza nawiasami i usunąć wszystkie sprawdzenia, co doprowadzi do ponownego wygenerowania identyfikatora w każdym żądaniu. (Nie testowałem wpływu tego podejścia na wydajność i mogę tylko powiedzieć, że funkcja session_regenerate_id (true) zasadniczo wykonuje tylko 4 akcje: generowanie nowego identyfikatora, tworzenie nagłówka z pliku cookie sesji, usuwanie starego i tworzenie nowego pliku sesji).

Liryczna dygresja: Jeśli trojan okaże się na tyle sprytny, że nie wyśle \u200b\u200bplików cookie do atakującego, ale sam zorganizuje wysłanie wcześniej przygotowanego fałszywego żądania natychmiast po otrzymaniu pliku cookie, opisana powyżej metoda najprawdopodobniej nie będzie w stanie ochronić się przed takim atakiem, ponieważ między momentem, w którym trojan otrzyma plik cookie a wysłaniem fałszywego Praktycznie nie będzie różnicy między żądaniem i jest bardzo prawdopodobne, że identyfikator sesji nie zostanie w tym momencie ponownie wygenerowany.

Możliwość jednoczesnej pracy w jednej przeglądarce w imieniu kilku użytkowników

Ostatnim zadaniem, które chciałbym rozważyć, jest możliwość jednoczesnej pracy w jednej przeglądarce dla kilku użytkowników. Ta funkcja jest szczególnie przydatna na etapie testowania, gdy musisz emulować jednoczesną pracę użytkowników i zaleca się to zrobić w ulubionej przeglądarce, zamiast korzystać z całego dostępnego arsenału lub otwierać wielu instancji przeglądarki w trybie incognito.

W naszych poprzednich przykładach nie ustawialiśmy jawnie nazwy sesji, więc użyto domyślnej nazwy PHP (PHPSESSID). Oznacza to, że wszystkie sesje, które utworzyliśmy do tej pory, wysyłały pliki cookie do przeglądarki pod nazwą PHPSESSID. Oczywiście, jeśli nazwa pliku cookie jest zawsze taka sama, nie ma możliwości zorganizowania dwóch sesji o tej samej nazwie w ramach tej samej przeglądarki. Ale gdybyśmy użyli innej nazwy sesji dla każdego użytkownika, problem zostałby rozwiązany. Więc zróbmy to.

Funkcja startSession ($ isUserActivity \u003d true, $ prefix \u003d null) (... if (session_id ()) return true; // Jeśli w parametrach przekazany jest prefiks użytkownika, // ustaw unikalną nazwę sesji, która zawiera ten prefiks, // w przeciwnym razie ustaw nazwa wspólna dla wszystkich użytkowników (na przykład MYPROJECT) nazwa_sesji ("MYPROJECT". (prefiks $? "_". $ prefix: "")); ini_set ("session.cookie_lifetime", 0); if (! session_start ()) return false; ...)

Teraz pozostaje tylko upewnić się, że skrypt wywołujący przekazuje unikalny prefiks dla każdego użytkownika do funkcji startSession (). Można to zrobić na przykład przekazując prefiks w parametrach GET / POST każdego żądania lub poprzez dodatkowy plik cookie.

Wniosek

Podsumowując, podam pełny końcowy kod naszych funkcji do pracy sesje PHP, w tym wszystkie zadania omówione powyżej.

Funkcja startSession ($ isUserActivity \u003d true, $ prefix \u003d null) ($ sessionLifetime \u003d 300; $ idLifetime \u003d 60; if (session_id ()) return true; session_name ("MYPROJECT". ($ Prefix? "_". $ Prefix: "")); ini_set ("session.cookie_lifetime", 0); if (! session_start ()) return false; $ t \u003d time (); if ($ sessionLifetime) (if (isset ($ _ SESSION ["lastactivity"] ) && $ t - $ _ SESSION ["lastactivity"]\u003e \u003d $ sessionLifetime) (destruSession (); return false;) else (if ($ isUserActivity) $ _SESSION ["lastactivity"] \u003d $ t;)) if ($ idLifetime) ) (if (isset ($ _ SESSION ["starttime"])) (if ($ t - $ _ SESSION ["starttime"]\u003e \u003d $ idLifetime) (session_regenerate_id (true); $ _SESSION ["starttime"] \u003d $ t; )) else ($ _SESSION ["starttime"] \u003d $ t;)) return true;) function destruSession () (if (session_id ()) (session_unset (); setcookie (session_name (), session_id (), time () -60 * 60 * 24); session_destroy ();))

Miejmy nadzieję, że ten artykuł pozwoli zaoszczędzić trochę czasu tym, którzy nigdy tak naprawdę nie weszli w mechanizm sesji, i zapewni wystarczające zrozumienie tego mechanizmu tym, którzy dopiero zaczynają zapoznawać się z PHP.

.
W tym artykule dodamy do naszej rejestracji czekmi- pocztaadresy, automatyczne logowanie i odzyskiwanie zapomniane hasło ... Przed rozpoczęciem lekcji upewnij się, że funkcja działa na Twoim serwerze poczta ().

Zacznijmy od dodania pól do tabeli « użytkowników» ... Potrzebujemy pola do przechowywania adresu e-mail, pola dla stanu użytkownika (0 - nieaktywny, 1 - aktywowany) oraz pola z datą rejestracji.





Następnie musisz poprawić save_user.phppoprzez dodanie sprawdzenia poprawności adresu e-mail i wysłanie listu potwierdzającego rejestrację. List zawiera odnośnik z dwiema zmiennymi przekazanymi przez metodę get : login i wygenerowany, unikalny dla każdego użytkownika kod. Potrzebujemy kodu, aby użytkownik nie mógł aktywować swojego konta bez listu, a to da nam pewność, że wprowadzony adres e-mail naprawdę należy do niego. Dodajmy następujący kod, po wyodrębnieniu przesłanych danych ze zmiennych globalnych:

If (isset ($ _ POST ["email"])) ($ email \u003d $ _POST ["email"]; if ($ email \u003d\u003d "") (unset ($ email);))
if (puste ($ login) lub puste ($ hasło) lub puste ($ kod) lub puste ($ email))
// dodaj zmienną za pomocąmi- pocztaadres
// jeśli użytkownik nie podał nazwy użytkownika ani hasła, to wystawiamy błąd i zatrzymujemy skrypt
{
exit ("Nie podałeś wszystkich informacji, wróć i wypełnij wszystkie pola!"); // przestań wykonywać skrypty
}
if (! preg_match ("/ [email chroniony]+ \\. (2,3) / i ", $ email)) // sprawdź adres e-mail wyrażenia regularne dla poprawności
(zakończ ("Podano nieprawidłowy adres e-mail!");)

We wniosku o dodanie nowego użytkownika należy również podać datę rejestracji. Jeśli dane zostały pomyślnie wprowadzone do bazy danych, a użytkownik jest zarejestrowany, należy wysłać wiadomość na podany adres:

// jeśli nie, to zapisz dane
$ result2 \u003d mysql_query ("INSERT INTO users (login, password, avatar, email, date) VALUES (" $ login "," $ password "," $ avatar "," $ email ", NOW ())");
// Sprawdź, czy są jakieś błędy
if ($ result2 \u003d\u003d "TRUE")
{
$ result3 \u003d mysql_query ("SELECT id FROM users WHERE login \u003d" $ login "", $ db); // pobierz ID użytkownika. Dzięki niemu będziemy mieć unikalny kod aktywacja, ponieważ nie mogą być dwa identyczne identyfikatory.
$ myrow3 \u003d mysql_fetch_array ($ result3);
$ aktywacja \u003d md5 ($ myrow3 ["id"]). md5 ($ login); // kodaktywacjakonto. Zaszyfrujmy identyfikator i zalogujmy się za pomocą funkcji md5. Jest mało prawdopodobne, aby użytkownik był w stanie ręcznie wybrać taką kombinację za pomocą paska adresu.
$ subject \u003d "Potwierdzenie rejestracji"; //Temat wiadomości
$ message \u003d "Witaj! Dziękujemy za rejestrację na citename.ru \\ nTwój login:". $ login. "\\ n
Kliknij link, aby aktywować swoje konto: \\ nhttp: //localhost/test3/activation.php? Login \u003d ". $ Login." & Code \u003d ". $ Activation." \\ N Pozdrawiam, \\ n
Administracja citename.ru "; // treść wiadomości
mail ($ email, $ subject, $ message, "Content-type: text / plane; Charset \u003d windows-1251 \\ r \\ n"); // wysłać wiadomość

Echo "Na Twój adres e-mail został wysłany e-mail z linkiem do potwierdzenia rejestracji. Uwaga! Link jest ważny 1 godzinę. Strona główna"; // mowa o e-mailu wysłanym do użytkownika
}

Wiadomość wysłana! Teraz użytkownik otworzy go i podąży za podanym linkiem do strony, która sprawdzi kod aktywacyjny. Po upewnieniu się, że kod jest poprawny, potwierdzamy rejestrację zmieniając wartość pola w bazie danych aktywacja od „0” do „1”.

Utwórz plik activation.php

include ("bd.php"); // plikbd. php powinien znajdować się w tym samym folderze co wszyscy inni, jeśli tak nie jest, po prostu zmień ścieżkę
$ result4 \u003d mysql_query ("WYBIERZ avatar Z użytkowników WHERE aktywacja \u003d" 0 "AND UNIX_TIMESTAMP () - UNIX_TIMESTAMP (data)\u003e 3600"); // pobierz awatary tych użytkowników, którzy nie aktywowali swojego konta w ciągu godziny. Dlatego muszą zostać usunięte z bazy danych, podobnie jak pliki ich awatarów
if (mysql_num_rows ($ wynik4)\u003e 0) (
$ myrow4 \u003d mysql_fetch_array ($ result4);
zrobić
{
// usuwa awatary w pętli, jeśli nie są standardowe
if ($ myrow4 ["avatar"] \u003d\u003d "avatars / net-avatara.jpg") ($ a \u003d "nic nie rób";)
else (
odłącz ($ myrow4 ["avatar"]); // usuń plik
}
}
while ($ myrow4 \u003d mysql_fetch_array ($ result4));
}
mysql_query ("USUŃ OD użytkowników WHERE aktywacja \u003d" 0 "AND UNIX_TIMESTAMP () - UNIX_TIMESTAMP (data)\u003e 3600"); // usuń użytkowników z bazy danych
if (isset ($ _ GET ["kod"])) ($ kod \u003d $ _ GET ["kod"];) //kod potwierdzający
jeszcze
(zakończ ("Weszłeś na stronę bez kodu potwierdzającego!");) // jeśli nie określonokod, wtedy podajemy błąd
if (isset ($ _ GET ["login"])) ($ login \u003d $ _ GET ["login"];) // zaloguj się, aby aktywować
jeszcze
(zakończ ("Wchodzisz na stronę bez logowania!");) // jeśli nie podałeś loginu, wystawiamy błąd
$ result \u003d mysql_query ("SELECT id FROM users WHERE login \u003d" $ login "", $ db); // pobierz identyfikator użytkownika z podanym loginem
$ aktywacja \u003d md5 ($ myrow ["id"]). md5 ($ login); // utwórz ten sam kod potwierdzający
if ($ aktywacja \u003d\u003d $ kod) ( // porównaj otrzymane zurl i wygenerowany kod
mysql_query ("UPDATE users SET aktywacja \u003d" 1 "WHERE login \u003d" $ login "", $ db); // jeśli równe, aktywuj użytkownika
echo "Twój e-mail został zweryfikowany! Teraz możesz wejść na stronę używając swojej nazwy użytkownika! Strona główna";
}
else (echo "Błąd! Twój adres e-mail nie został zweryfikowany! Strona główna";
// jeśli uzyskano zurl a wygenerowany kod nie jest równy, wtedy podajemy błąd
}
?>

Adres e-mail został potwierdzony, teraz wiemy, że należy do tego użytkownika, będzie można wysłać do niego hasło, jeśli użytkownik je zapomni, lub inne powiadomienia. Ale jaka jest różnica między aktywowanymi a nieaktywowanymi użytkownikami? Obaj mogą wejść na stronę, dlatego musimy ograniczyć dostęp tym, którzy nie są aktywowani. Otwórzmy plik testreg. php i dodaj jeszcze jeden warunek w zapytaniu do bazy danych:

$ wynik \u003d mysql_query ("SELECT * FROM users WHERE login \u003d" $ login "AND hasło \u003d" $ hasło "AND aktywacja \u003d" 1 "", $ db); // pobranie z bazy danych wszystkich danych o użytkowniku z podanym loginem
// Dodaliśmy "Iaktywacja\u003d "1" ", czyli użytkownik będzie przeszukiwany tylko wśród aktywowanych. Pożądane jest dodanie tego warunku do innych podobnych kontroli danych użytkownika.

Jeśli użytkownik zapomni hasła, wówczas w takim przypadku należy wyświetlić link do strona główna, za pomocą którego może go przywrócić, a także możesz od razu zaznaczyć pole wyboru automatycznego logowania.

Automatyczne logowanie.






Zarejestruj się teraz


Zapomniałeś hasła?

Jest łącze, ale nie ma pliku. Napiszmy wysłać_ przechodzić. php... W nim zapytamy użytkownika o login i adres e-mail. Jeżeli wpisany e-mail i login znajdują się w bazie, to do niej wyślemy nowe hasłojeśli użytkownik zapomniał starego, ponieważ podczas rejestracji upewniliśmy się, że adres e-mail jest prawidłowy.

if (isset ($ _ POST ["login"])) ($ login \u003d $ _POST ["login"]; if ($ login \u003d\u003d "") (unset ($ login);)) // wprowadź login wprowadzony przez użytkownika do zmiennej $ login, jeśli jest pusta, zniszcz zmienną
if (isset ($ _ POST ["email"])) ($ email \u003d $ _POST ["email"]; if ($ email \u003d\u003d "") (unset ($ email);)) // wprowadź adres e-mail podany przez użytkownika, jeśli jest pusty, zniszcz zmienną
if (isset ($ login) i isset ($ email)) ( // jeśli wymagane zmienne istnieją

Uwzględnij ("bd.php");

$ wynik \u003d mysql_query ("WYBIERZ id \u200b\u200bużytkowników WHERE login \u003d" $ login "AND email \u003d" $ email "AND aktywacja \u003d" 1 "", $ db); // takiczywużytkownikmi- poczta
$ myrow \u003d mysql_fetch_array ($ wynik);
if (puste ($ myrow ["id"]) lub $ myrow ["id"] \u003d\u003d "") (
// jeśli nie ma aktywowanego użytkownika z tym loginem i adresem e-mail
exit ("Żaden użytkownik o tym adresie e-mail nie został znaleziony w żadnej bazie danych CIA :) Strona główna");
}
// jeśli zostanie znaleziony użytkownik z taką nazwą użytkownika i adresem e-mail, to należy wygenerować dla niego losowe hasło, zaktualizować je w bazie danych i wysłać na e-mail
$ datenow \u003d date ("YmdHis"); // pobierz datę
$ new_password \u003d md5 ($ datenow); // zaszyfruj datę
$ nowe_hasło \u003d substr ($ nowe_hasło, 2, 6); // wyodrębnij 6 znaków z szyfru, zaczynając od drugiego. To będzie nasze losowe hasło. Następnie zapiszemy go do bazy danych, szyfrując w taki sam sposób jak zwykle.

$ new_password_sh \u003d strrev (md5 ($ nowe_password)). "b3p6f"; // zaszyfrowane
mysql_query ("UPDATE users SET hasło \u003d" $ new_password_sh "WHERE login \u003d" $ login "", $ db); // zaktualizowanywbaza
// utwórz wiadomość

$ message \u003d "Hello,". $ login. "! Wygenerowaliśmy dla Ciebie hasło, teraz możesz wejść na stronę citename.ru używając go. Po wejściu zaleca się jego zmianę. Hasło: \\ n". $ new_password; //Wiadomość tekstowa
mail ($ email, "Odzyskiwanie hasła", $ message, "Typ treści: tekst / samolot; Zestaw znaków \u003d windows-1251 \\ r \\ n"); // wysłaćwiadomość

Echo " List z hasłem został wysłany na Twój e-mail. Po 5 sekundach zostaniesz przeniesiony. Jeśli nie chcesz czekać, kliknij tutaj. "; // przekieruj użytkownika
}
else ( // jeśli żadne dane nie zostały jeszcze wprowadzone
Echo "


Zapomniałeś hasła?


Zapomniałeś hasła?



Wpisz swój login:



Wprowadź swój email:






";
}
?>

Następnie dokonamy automatycznego logowania. Będzie to działać w następujący sposób: po pomyślnym zalogowaniu się z wciśniętym polem wyboru w pliku cookie zostanie wpisane auto \u003d „yes”. Jeśli serwer zobaczy, że auto \u003d „yes” w przeglądarce, rozpocznie sesję i pobierze zmienne z pliku cookie. Następnie uruchomione sesje są porównywane z bazą danych.

Otwórzmy testreg. php i dodaj kod po udanym logowaniu:

Jeśli (isset ($ _ POST ["zapisz"])) (
// Jeśli użytkownik chce, aby jego dane zostały zapisane do późniejszego logowania, zapisujemy je w plikach cookies jego przeglądarki

setcookie ("id", $ myrow ["id"], time () + 9999999);)
if (isset ($ _ POST ["autovhod"])) (
// Jeśli użytkownik chce wejść na stronę automatycznie
setcookie ("auto", "tak", czas () + 9999999);
setcookie ("login", $ _POST ["login"], time () + 9999999);
setcookie ("hasło", $ _POST ["hasło"], czas () + 9999999);
setcookie ("id", $ myrow ["id"], time () + 9999999);)

Teraz musisz rozpocząć sesję w odpowiednim miejscu, jeśli istnieje automatyczne logowanie. Otwórzmy index.php i napisz na samym początku strony:

// cała procedura działa na sesjach. To w niej przechowywane są dane użytkownika, gdy przebywa on w serwisie. Bardzo ważne jest, aby uruchomić je na samym początku strony !!!
session_start ();
include ("bd.php"); // plik bd.php powinien znajdować się w tym samym folderze co wszyscy inni, jeśli tak nie jest, po prostu zmień ścieżkę
if (isset ($ _ COOKIE ["auto"]) i isset ($ _ COOKIE ["login"]) i isset ($ _ COOKIE ["hasło"]))
{// jeśli są wymagane zmienne
if ($ _COOKIE ["auto"] \u003d\u003d "tak") ( // jeśli użytkownik chce się zalogować automatycznie, rozpocznij sesje
$ _SESSION ["hasło"] \u003d strrev (md5 ($ _ COOKIE ["hasło"])). "B3p6f"; // w plikach cookie hasło nie było zaszyfrowane, ale w sesjach zwykle przechowujemy je w postaci zaszyfrowanej
$ _SESSION ["login"] \u003d $ _ COOKIE ["login"]; // sesjazzaloguj sie
$ _SESSION ["id"] \u003d $ _ COOKIE ["id"]; //identyfikator użytkownika
}
}

Teraz nawet wyjście nie pomoże nam zmienić użytkownika! W wyjście. php sesje są usuwane, które nadal są tworzone indeks. phpdzięki ciasteczkom, które są przechowywane przez bardzo długi czas! Mimo wszystko naprawmy plik wyjście. phpw przeciwnym razie nie działa w przypadku automatycznego logowania. Wystarczy wyczyścić automatyczne logowanie w ciasteczku, po usunięciu zmiennych z sesji:

Setcookie ("auto", "", czas () + 9999999); // wyczyść automatyczne logowanie

Konieczne jest również dodanie do aktualizacja_ użytkownik. php po aktualizacji loginu w sesji:

$ _SESSION ["login"] \u003d $ login; // Zaktualizuj login w sesji
if (isset ($ _ COOKIE ["login"])) (
setcookie ("login", $ login, time () + 9999999); // Aktualizacjazaloguj siewciasteczka
}

I to samo z hasłem

$ result4 \u003d mysql_query ("UPDATE users SET hasło \u003d" $ password "WHERE login \u003d" $ old_login "", $ db); // aktualizacjahasło
if ($ result4 \u003d\u003d "TRUE") ( // jeśli prawda, zaktualizuj ją w sesji
$ _SESSION ["hasło"] \u003d $ hasło;
if (isset ($ _ COOKIE ["hasło"])) (
setcookie ("hasło", $ _ POST ["hasło"], czas () + 9999999); // Aktualizacjahasłowciasteczka, jeślionejest
}

Otóż \u200b\u200bto. Mam nadzieję, że ci się uda! Powodzenia!

Dzień dobry przyjaciele! Przyjrzyjmy się rejestracji użytkownika w PHP razem z Tobą. Najpierw zdefiniujmy warunki rejestracji naszego użytkownika:

  • Szyfrujemy hasło za pomocą algorytmu MD5
  • Hasło będzie „solone”
  • Sprawdź, czy logowanie jest zajęte
  • Aktywacja użytkownika listownie.
  • Pisanie i przechowywanie danych w MySQL DBMS

Aby napisać ten skrypt, musimy zrozumieć, czym jest rejestracja użytkownika. Rejestracja użytkownika to pozyskiwanie prawdziwych danych użytkownika, przetwarzanie i przechowywanie danych.

Aby wyjaśnić w prostych słowach, rejestracja to tylko zapisanie i przechowywanie określonych danych, za pomocą których możemy autoryzować użytkownika w naszym przypadku - jest to Login i Hasło.

Autoryzacja to nadanie określonej osobie lub grupie osób uprawnień do wykonywania określonych czynności, a także proces weryfikacji tych uprawnień przy próbie wykonania tych czynności. Mówiąc najprościej, korzystając z autoryzacji, możemy zróżnicować dostęp do jednej lub drugiej treści na naszej stronie internetowej.

Rozważmy strukturę katalogów skryptów do wykonania naszej rejestracji z uprawnieniami. Musimy rozbić skrypty na logiczne komponenty. W osobnym katalogu umieściliśmy moduły rejestracji i autoryzacji. W oddzielnych katalogach umieścimy również połączenie z bazą danych. MySQL, plik funkcji niestandardowych, plik stylu CSS i nasz szablon HTML... Ta struktura pozwala na szybkie poruszanie się po skryptach. Wyobraź sobie, że masz dużą witrynę z mnóstwem modułów itp. a jak nie ma porządku, bardzo trudno będzie znaleźć coś w takim bałaganie.

Ponieważ będziemy przechowywać wszystkie dane w formacie MySQL DBMS, następnie stwórzmy małą tabelkę, w której będziemy przechowywać dane rejestracyjne.

Najpierw musisz utworzyć tabelę w bazie danych. Stół zostanie wywołany bez_reg Gdzie bez jest przedrostkiem tabeli, a rej Nazwa tabeli.

Struktura stołu: bez_reg

- - Struktura tabeli `bez_reg` - TWORZENIE TABELI, JEŚLI NIE ISTNIEJE bez_reg` (ʻid` int (11) NOT NULL AUTO_INCREMENT,` login` varchar (200) NOT NULL, `pass` varchar (32) NOT NULL , `salt` varchar (32) NOT NULL, ʻactive_hex` varchar (32) NOT NULL,` status` int (1) NOT NULL, PRIMARY KEY (ʻid`)) ENGINE \u003d MyISAM DEFAULT CHARSET \u003d utf8 AUTO_INCREMENT \u003d 1;

Teraz stwórzmy główne skrypty do dalszej pracy.

Plik INDEX.PHP

Plik CONFIG.PHP

"); ?>

Plik 404.html

błąd 404

błąd 404

Na stronie wystąpił błąd 404

Wracać

Plik BD.PHP

Plik INDEX.HTML

Rejestracja użytkownika PHP MySQL z aktywacją przez e-mail

Plik FUNCT.PHP

"." \\ n "; if (is_array ($ data)) (foreach ($ data as $ val) $ err. \u003d"

  • „. $ val.”
  • "." \\ n ";) else $ err. \u003d"
  • „. $ data”.
  • "." \\ n "; $ err. \u003d""." \\ n "; return $ err;) / ** Proste opakowanie dla zapytań MySQL * @param string $ sql * / function mysqlQuery ($ sql) ($ res \u003d mysql_query ($ sql); / * Sprawdzanie wyniku To pokazuje rzeczywiste zapytanie wysłane do MySQL oraz błąd. Przydatne do debugowania. * / if (! $ res) ($ message \u003d "Invalid query:". mysql_error (). "\\ n"; $ message. \u003d "Query full : ". $ sql; die ($ message);) return $ res;) / ** Prosty generator soli * @param string $ sql * / function salt () ($ salt \u003d substr (md5 (uniqid ()), - 8); powrót $ sól;)

    Przejdźmy do pisania rejestracji. Najpierw będziemy musieli wykonać szablon formularza rejestracyjnego, aby użytkownik mógł wprowadzić swoje dane do przetwarzania. Następnie będziemy musieli napisać samą obsługę formularza, która sprawdzi poprawność wprowadzonych danych użytkownika. Po pomyślnej weryfikacji danych wpisujemy je do naszej bazy danych i wysyłamy list do użytkownika w celu aktywacji konta.

    Plik REG.PHP

    Zarejestrowałeś się pomyślnie! Proszę aktywować konto !!"; // Aktywujemy konto if (isset ($ _ GET [" key "])) (// Sprawdź klucz $ sql \u003d" SELECT * FROM "". BEZ_DBPREFIX. "Reg` WHERE ʻactive_hex` \u003d" ". Escape_str ( $ _GET ["key"]). "" "; $ Res \u003d mysqlQuery ($ sql); if (mysql_num_rows ($ res) \u003d\u003d 0) $ err \u003d" Klucz aktywacyjny jest nieprawidłowy! "; // Sprawdź błędy i wyświetl użytkownikowi if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Pobierz adres użytkownika $ row \u003d mysql_fetch_assoc ($ res); $ email \u003d $ row ["login"]; // Aktywuj konto user $ sql \u003d "UPDATE`". BEZ_DBPREFIX. "reg` SET` status` \u003d 1 WHERE` login` \u003d "". $ email. "" "; $ res \u003d mysqlQuery ($ sql); // Wyślij e-mail do aktywacji $ title \u003d "(! LANG: Twoje konto w witrynie http: // zostało pomyślnie aktywowane"; $message = "Поздравляю Вас, Ваш аккаунт на http://сайт успешно активирован"; sendMessageMail($email, BEZ_MAIL_AUTOR, $title, $message); /*Перенаправляем пользователя на нужную нам страницу*/ header("Location:". BEZ_HOST ."less/reg/?mode=reg&active=ok"); exit; } } /*Если нажата кнопка на регистрацию, начинаем проверку*/ if(isset($_POST["submit"])) { //Утюжим пришедшие данные if(empty($_POST["email"])) $err = "Поле Email не может быть пустым!"; else { if(!preg_match("/^!} [email chroniony](+ \\.) + (2,6) $ / i ", $ _POST [" email "])) $ err \u003d" E-mail wprowadzony niepoprawnie "." \\ N ";) if (pusty ($ _ POST [ "pass"])) $ err \u003d "Pole hasła nie może być puste"; if (puste ($ _ POST ["pass2"])) $ err \u003d "Pole potwierdzenia hasła nie może być puste"; // Sprawdź błędy i wyświetl użytkownikowi if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Kontynuuj sprawdzanie wprowadzonych danych Sprawdź pasujące hasła * / if ($ _ POST ["pass"]! \u003d $ _POST ["pass2" ]) $ err \u003d "Hasła nie pasują"; // Sprawdź błędy i wyświetl je użytkownikowi if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Sprawdź, czy mamy takiego użytkownika w bazie danych * / $ sql \u003d "SELECT` login` FROM". BEZ_DBPREFIX. "reg` WHERE` login` \u003d" ". escape_str ($ _ POST [" email "])." ""; $ res \u003d mysqlQuery ($ sql); if (mysql_num_rows ($ res)\u003e 0) $ err \u003d "Przepraszamy Zaloguj się: ". $ _POST [" email "]." zajęty! "; // Sprawdź, czy nie ma błędów i wyświetl je użytkownikowi if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Pobierz HASH soli $ salt \u003d salt (); // Sól hasło $ pass \u003d md5 (md5 ($ _ POST ["pass"]). $ salt); / * Jeśli wszystko jest w porządku, zapisz dane do bazy danych * / $ sql \u003d "INSERT INTO`". BEZ_DBPREFIX. "reg` VALUES (" "," " . escape_str ($ _ POST ["email"]). "", "". $ pass. "", "". $ sól. "", "". md5 ($ sól). "", 0) "; $ res \u003d mysqlQuery ($ sql); // Wysyłamy wiadomość e-mail w celu aktywacji $ url \u003d BEZ_HOST. "less / reg /? mode \u003d reg & key \u003d". md5 ($ salt); $ title \u003d "(! LANG: Rejestracja na http: / /stronie internetowej"; $message = "Для активации Вашего акаунта пройдите по ссылке ". $url .""; sendMessageMail($_POST["email"], BEZ_MAIL_AUTOR, $title, $message); //Сбрасываем параметры header("Location:". BEZ_HOST ."less/reg/?mode=reg&status=ok"); exit; } } } } ?>!}

    Plik REG_FORM.HTML

    Rejestracja użytkownika PHP MySQL z aktywacją przez e-mail

    E-mail *:
    Hasło *:
    Potwierdzenie hasła *:

    Pola z ikoną * są wymagane

    Ponieważ jesteśmy gotowi do rejestracji użytkowników, czas napisać autoryzację. Stwórzmy formularz do autoryzacji użytkownika, następnie napiszmy procedurę obsługi formularza autoryzacji i na koniec stworzymy skrypt show.php który pokaże nam, czy mamy autoryzację w systemie, czy nie.

    Plik AUTH.PHP

    0) echo showErrorMessage ($ err); else (/ * Utwórz zapytanie do pobrania z bazy danych w celu sprawdzenia autentyczności użytkownika * / $ sql \u003d "SELECT * FROM`". BEZ_DBPREFIX. "reg` WHERE` login` \u003d "". escape_str ($ _ POST ["email"]) . "" AND `status` \u003d 1"; $ res \u003d mysqlQuery ($ sql); // Jeśli login pasuje, sprawdź hasło if (mysql_num_rows ($ res)\u003e 0) (// Pobierz dane z tabeli $ row \u003d mysql_fetch_assoc ( $ res); if (md5 (md5 ($ _ POST ["pass"]). $ row ["salt"]) \u003d\u003d $ row ["pass"]) ($ _SESSION ["user"] \u003d true; // Resetuj nagłówek parametrów ("Lokalizacja:". BEZ_HOST. "Less / reg /? Mode \u003d auth"); exit;) else echo showErrorMessage ("Złe hasło!");) Else echo showErrorMessage ("Login ". $ _POST [" email "]." nie znaleziono! ");))?\u003e

    Dla tych, którzy mają najnowszą wersję PHP, publikuję ten skrypt przy użyciu ChNP od ekspansja MySQL przestarzałe i usunięte z nowszej wersji PHP. Pobierz rejestrację i autoryzację php mysql pdo

    Archiwum zostało zaktualizowane 24 lutego 2015 r.

    Uwaga: Jeśli używasz tego skryptu na serwerze lokalnym, takim jak DENWER, XAMPP, to nie powinieneś czekać na listy do swojej skrzynki pocztowej. Litery są puste wyślij maila... W Denwer można je znaleźć po drodze Z: \\ tmp \\! Sendmail \\ możesz otworzyć te pliki w dowolnym kliencie pocztowym.

    Nauczymy się prostego uwierzytelniania użytkownika w serwisie. Witryna może mieć tylko strony dla autoryzowanych użytkowników i będą one w pełni funkcjonować, jeśli dodamy do nich nasz blok uwierzytelniający. Aby go utworzyć, potrzebujesz bazy danych MySQL. Może mieć 5 kolumn (minimum) lub więcej, jeśli chcesz dodać informacje o użytkowniku. Nazwijmy bazę danych „Userauth”.

    Utwórzmy w nim następujące pola: ID do zliczania liczby użytkowników, UID dla unikalnego numeru identyfikacyjnego użytkownika, Nazwa użytkownika dla nazwy użytkownika, Email dla jego adresu e-mail oraz Hasło dla hasła. Możesz wykorzystać istniejącą bazę danych do autoryzacji użytkowników, tak jak w przypadku nowej bazy, stwórz w niej poniższą tabelę.

    Kod MySQL

    CREATE TABLE ʻusers` (ʻID` int (11) NOT NULL AUTO_INCREMENT, ʻUID` int (11) NOT NULL, ʻUsername` text NOT NULL, ʻEmail` text NOT NULL, `Password` text NOT NULL, PRIMARY KEY (ʻID`)) ENGINE \u003d MyISAM DEFAULT CHARSET \u003d utf8 AUTO_INCREMENT \u003d 1;

    Teraz stwórzmy plik „sql.php”. Odpowiada za połączenie z bazą danych. Ten kod najpierw tworzy zmienne dla serwera i użytkownika, kiedy łączy się z serwerem. Po drugie, wybierze bazę danych, w tym przypadku „USERAUTH”. Ten plik musi być połączony z "log.php" i "reg.php", aby uzyskać dostęp do bazy danych.

    Kod PHP

    // Twoja nazwa użytkownika MySQL $ pass \u003d "redere"; // hasło $ conn \u003d mysql_connect ($ server, $ user, $ pass); // połączyć się z serwerem $ db \u003d mysql_select_db ("userauth", $ conn); // wybierz bazę danych if (! $ db) ( // jeśli nie można wybrać bazy danych echo "Przepraszamy, błąd: (/\u003e"; // Wyświetla komunikat o błędzie wyjście (); // Zezwala na działanie innych skryptów PHP } ?>

    Następna jest strona logowania, nazwijmy ją „login.php”. Najpierw sprawdza wprowadzone dane pod kątem błędów. Strona zawiera pola na nazwę użytkownika, hasło, przycisk przesyłania i łącze rejestracyjne. Po kliknięciu przez użytkownika przycisku „Zaloguj się”, formularz zostanie przetworzony przez kod z pliku „log.php”, po czym nastąpi zalogowanie do systemu.

    Kod PHP

    0) { // jeśli występują błędy sesji $ err \u003d "

    "; // Uruchom tabelę foreach ($ _SESSION [" ERRMSG "] as $ msg) ( // rozpoznaje każdy błąd $ err. \u003d " "; // zapisz to do zmiennej ) $ err. \u003d "
    „. $ msg.”
    "; // zamknij tabelę nieustawiona ($ _SESSION ["ERRMSG"]); // usuń sesję } ?> Forma loginu
    Nazwa Użytkownika
    Hasło
    Zameldować się

    Następnie piszemy skrypt do logowania się do systemu. Nazwijmy to „log.php”. Posiada funkcję czyszczenia danych wejściowych z iniekcji SQL, które mogą zepsuć skrypt. Po drugie, pobiera dane formularza i sprawdza je. Jeśli dane wejściowe są poprawne, skrypt odsyła użytkownika do strony autoryzowanych użytkowników, jeśli nie, ustawia błędy i odsyła użytkownika do strony logowania.

    Kod PHP

    // rozpoczęcie sesji nagrywania function Fix ($ str) (// wyczyść pola $ str \u003d trim ($ str); if (get_magic_quotes_gpc ()) ($ str \u003d stripslashes ($ str);) // tablica do przechowywania błędów $ errflag \u003d false; // flaga błędu $ username \u003d Fix ($ _ POST ["nazwa użytkownika"]); //Nazwa Użytkownika $ password \u003d Fix ($ _ POST ["hasło"]); // hasło) // sprawdź hasło if ($ password \u003d\u003d "") ($ errmsg \u003d "Brak hasła"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu) // jeśli flaga błędu jest ustawiona, kieruje z powrotem do formularza rejestracyjnego // rejestruj błędy session_write_close (); // Zamknij sesję // przekierowanie wyjście (); ) // zapytanie do bazy danych $ qry \u003d "SELECT * FROM ʻusers` WHERE ʻUsername` \u003d" $ username "AND` Password` \u003d" ". md5 ($ password)." ""; $ wynik \u003d mysql_query ($ qry); // sprawdź, czy żądanie się powiodło (czy są na nim dane) if (mysql_num_rows ($ wynik) \u003d\u003d 1) (while ($ row \u003d mysql_fetch_assoc ($ wynik)) ($ _SESSION ["UID"] \u003d $ row ["UID"]; // pobierz UID z bazy danych i umieść go w sesji $ _SESSION ["USERNAME"] \u003d $ nazwa użytkownika; // określa, czy nazwa użytkownika pasuje do sesji session_write_close (); // Zamknij sesję nagłówek ("lokalizacja: member.php"); // przekierowanie )) else ($ _SESSION ["ERRMSG"] \u003d "Nieprawidłowa nazwa użytkownika lub hasło"; // błąd session_write_close (); // Zamknij sesję nagłówek ("lokalizacja: login.php"); // przekierowanie wyjście (); )?\u003e

    Utwórzmy stronę rejestracyjną, nazwijmy ją „register.php”. Jest podobna do strony logowania, z tą różnicą, że ma kilka dodatkowych pól, a zamiast linku rejestracyjnego link do login.php w przypadku, gdy użytkownik ma już konto.

    Kod PHP

    0) { // jeśli występują błędy sesji $ err \u003d "

    "; // początek tabeli foreach ($ _SESSION [" ERRMSG "] as $ msg) ( // ustawia każdy błąd $ err. \u003d " "; // zapisz je do zmiennej ) $ err. \u003d "
    „. $ msg.”
    "; // koniec tabeli nieustawiony ($ _SESSION [" ERRMSG "]); // zniszcz sesję } ?> Formularz rejestracyjny
    Nazwa Użytkownika
    E-mail
    Hasło
    Powtórz hasło
    Mam konto

    Teraz stwórzmy skrypt rejestracyjny w pliku „reg.php”. Będzie zawierał „sql.php”, aby połączyć się z bazą danych. Używa tej samej funkcji, co w skrypcie logowania, aby wyczyścić pole wejściowe. Zmienne są ustawione dla możliwych błędów. Next to funkcja do tworzenia unikatowego identyfikatora, który nigdy wcześniej nie był dostarczany. Następnie dane są pobierane z formularza rejestracyjnego i weryfikowane. Sprawdza, czy adres e-mail ma prawidłowy format i czy hasło zostało ponownie wprowadzone poprawnie. Następnie skrypt sprawdza, czy w bazie danych znajduje się użytkownik o tej samej nazwie, a jeśli tak, zgłasza błąd. Na koniec kod dodaje użytkownika do bazy danych.

    Kod PHP

    // rozpoczęcie sesji nagrywania function Fix ($ str) (// wyczyść pola $ str \u003d @trim ($ str); if (get_magic_quotes_gpc ()) ($ str \u003d stripslashes ($ str);) return mysql_real_escape_string($ str); ) $ errmsg \u003d array (); // tablica do przechowywania błędów $ errflag \u003d false; // flaga błędu $ UID \u003d "12323543534523453451465685454"; // unikalny identyfikator $ username \u003d Fix ($ _ POST ["nazwa użytkownika"]); //Nazwa Użytkownika $ email \u003d $ _POST ["email"]; // Email $ password \u003d Fix ($ _ POST ["password"]); // hasło $ rpassword \u003d Fix ($ _ POST ["rpassword"]); // powtórz hasło // sprawdź nazwę użytkownika if ($ username \u003d\u003d "") ($ errmsg \u003d "Brak nazwy użytkownika"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu ) // sprawdź Email if (! eregi ("^ [_ a-z0-9 -] + (\\. [_ a-z0-9 -] +) * @ + (\\. +) * (\\. (2,3 )) $ ", $ email)) (// musi pasować do formatu: [email chroniony] $ errmsg \u003d "Nieprawidłowy e-mail"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu } // sprawdź hasło if ($ password \u003d\u003d "") ($ errmsg \u003d "Brak hasła"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu } // sprawdź powtórzenie hasła if ($ rpassword \u003d\u003d "") ($ errmsg \u003d "Brak powtórzonego hasła"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu } // sprawdź, czy hasło jest prawidłowe if (strcmp ($ hasło, $ rpassword)! \u003d 0) ($ errmsg \u003d "Hasła nie pasują"; // błąd $ errflag \u003d true; // podnosi flagę w przypadku błędu } // sprawdź, czy nazwa użytkownika jest wolna if ($ username! \u003d "") ($ qry \u003d "SELECT * FROM ʻusers` WHERE ʻUsername` \u003d" $ username ""; // Zapytanie MySQL $ result \u003d mysql_query ($ qry); if ($ result) (jeśli (mysql_num_rows ($ wynik)\u003e 0) ( // jeśli nazwa jest już używana $ errmsg \u003d "Nazwa użytkownika jest już w użyciu"; // Komunikat o błędzie $ errflag \u003d true; // podnosi flagę w przypadku błędu ) mysql_free_result ($ wynik); )) // jeśli dane nie przeszły walidacji, kieruje z powrotem do formularza rejestracyjnego if ($ errflag) ($ _SESSION ["ERRMSG"] \u003d $ errmsg; // Komunikat o błędzie session_write_close (); // Zamknij sesję nagłówek ("lokalizacja: register.php"); // przekierowanie wyjście (); ) // dodaj dane do bazy danych $ qry \u003d "INSERT INTO ʻuserauth`. ʻusers` (ʻUID`, ʻUsername`, ʻEmail`,` Password`) VALUES ("$ UID", "$ username", "$ email", "". md5 ($ hasło). "") "; $ wynik \u003d mysql_query ($ qry); // sprawdź, czy żądanie dodania powiodło się if ($ result) (echo "Dziękujemy za rejestrację". $ username. ". Zaloguj się tutaj"; exit ();) else (die (" Błąd, skontaktuj się później ");)?\u003e

    Musisz także stworzyć skrypt, który wyloguje użytkownika z systemu. Kończy sesję użytkownika o podanym unikalnym identyfikatorze i nazwie, a następnie przekierowuje użytkownika na stronę logowania.

    Kod PHP

    Wreszcie, skryptu „auth.php” można użyć do udostępnienia stron tylko autoryzowanym użytkownikom. Sprawdza dane logowania i, jeśli są prawidłowe, pozwala użytkownikowi przeglądać strony, a jeśli nie, prosi o zalogowanie. Ponadto, jeśli ktoś spróbuje zhakować witrynę, tworząc jedną z sesji, zostanie ona przerwana, jak w ogólnym przypadku.

    Kod PHP

    Jeden z warunków w powyższym kodzie jest przedmiotem pytania w.

    Poniższy kod należy wstawić na stronę dla autoryzowanych użytkowników, nazywa się go na przykład „member.php”, ale Twój może być nazywany jak chcesz.

    Kod PHP

    Masz dostęp do tej strony. Wyloguj ( )

    Uwierzytelnianie użytkownika jest gotowe!

    DZWONEK

    Są tacy, którzy czytają tę wiadomość przed wami.
    Zapisz się, aby otrzymywać najnowsze artykuły.
    E-mail
    Nazwa
    Nazwisko
    Jak chcesz przeczytać The Bell
    Bez spamu