THE BELL

Є ті, хто прочитали цю новину раніше вас.
Підпишіться, щоб отримувати статті свіжими.
Email
ім'я
Прізвище
Як ви хочете читати The Bell
без спаму

Технологія сесії в PHP є простим способом зберігання інформації для окремо взятого користувача сайту. Наприклад: товари, додані до кошика магазину, настройки повідомлень і т.д. При першому запиті сайту до сервера, в браузері зберігається в cookies унікальний ідентифікатор сесії користувача. Потім ідентифікатор або зв'язка ідентифікатора з IP адресою ідентифікує користувача. Це може використовуватися для збереження стану між запитами сторінок. Ідентифікатори сесій зазвичай відправляються браузеру через сесійну Cookie і використовуються для отримання наявних даних сесії.

сесії використовують просту технологію: PHP буде або отримувати дані існуючої сесії, використовуючи переданий ідентифікатор (зазвичай із сесійної cookie), Або, якщо нічого не передавалося, буде створена нова сесія. PHP заповнить суперглобального змінну $ _SESSION сесійного інформацією після того, як буде запущена сесія. Коли PHP завершує роботу, він автоматично серіалізуются вміст суперглобального змінної $ _SESSION і відправляє для збереження, використовуючи сесійну обробник для запису сесії.

За замовчуванням PHP використовує внутрішній обробник files для збереження сесій, який встановлений в INI-змінної session.save_handler. Цей оброблювач зберігає дані на сервері в директорії, зазначеної в конфигурационной директиві session.save_path.

Найпростіший приклад використання сесії, наприклад, висновок кількості звернень до сторінці для кожного користувача:

Яким способом можливе блокування сесій

На сайті php в секції опису роботи сесій є примітка (http://php.net/manual/ru/session.examples.basic.php):

Сесії, що використовують файли (за замовчуванням в PHP), Блокують файл сесії одразу під час відкриття сесії функцією session_start () або побічно при вказівці session.auto_start. Після блокування, жоден інший скрипт не може отримати доступ до цього ж файлу сесії, поки він не буде закритий або при завершенні скрипта або при виконанні функції session_write_close ().

Швидше за все це стане проблемою для сайтів, які активно використовують AJAX і роблять кілька одночасних запитів. Найпростішим шляхом вирішити цю проблему буде виклик функції session_write_close () відразу ж як тільки всі необхідні зміни в сесії будуть зроблені, переважно ближче до початку роботи скрипта. Також можна використовувати інший механізм сесії, який підтримує конкурентний доступ.

Останнім часом проблема блокування сесій стає все більш частою. Почасти це пов'язано з ускладненням сайтів і необхідністю виробляти більше обчислень на строне сервера, а так само з великим поширенням AJAX. На жаль, не завжди логіка програми, особливо якщо вона складна, дозволяє ефективно обмежити час блокування конкуруючих за сесію процесів. Ситуація ускладнюється ще тим, що 3-5 подібних клієнтів здатні швидко забити завислими і простоюють в очікуванні процесами PHP-Воркер, в результаті чого сайт почне видавати 5XX помилку .

Найпростіший приклад блокування сесій:

// тільки для одного скрипта ?>

Якщо відкрити цей файл спочатку в першій вкладці, а потім у другій - друга вкладка буде чекати, поки не допрацює перша. Тобто фактично друга вкладка буде чекати, поки перша не звільнить файл сесії (що займає в конкретному випадку 30 секунд). Дана проблема добре описана в блозі компанії 1С-Бітрікс на Habrahabr.

Які варіанти вирішення даної проблеми існують

Для зберігання сесій можна використовувати БД, такі як MySQL або PostgreSQL (Що не зовсім правильно, враховуючи можливості більшості БД і можливу швидкість роботи в даної задачі), Memcached (Не гарантує зберігання сесії, можливо її видалення) та Redis, Який ми вважаємо оптимальним сховищем. За швидкістю він не поступається Memcached, але при цьому може гарантувати збереження даних.

І найголовніше перевага Redis - при зберіганні в ньому сесій вони не блокуються.

В рамках нашої панелі управління () можна включити зберігання сесій в Redis для всіх сайтів на акаунті. Для цього необхідно перейти в розділ " сайти", І далі відзначити галочку -" Зберігати сесії всіх сайтів в Redis".

Додаткові матеріали

розділи

SSH

FTP

Веб-додатки

  • Загальні відомості по установці додатків (віртуальне оточення Docker)

діагностика проблем

Домени

  • Анулювання доменного імені в зоне.RU / РФ для якого Beget є реєстратором
  • Передача права адміністрування доменного імені.RU / РФ / .SU і міжнародних зонах (Зміна адміністратора домену)

Вітаю, шановне співтовариство.

Перш за все, хочу подякувати за дуже корисний ресурс. Не раз знаходив тут безліч цікавих ідей і практичних порад.

Мета цієї статті - висвітлити підводні камені використання сесій в PHP. Звичайно, є документація по PHP і маса прикладів, і дана стаття не претендує на повне керівництво. Вона покликана розкрити деякі нюанси роботи з сесіями і захистити розробників від непотрібної витрати часу.

Найпоширенішим прикладом використання сесій є, звичайно, авторизація користувачів. Почнемо з самої базової реалізації, щоб послідовно розвивати її в міру появи нових завдань.

(З метою економії місця і часу обмежимося в прикладах тільки самими функціями роботи з сесіями, замість того, щоб будувати тут повноцінне тестове додаток з красивою ієрархією класів, вичерпної обробкою помилок і іншими правильними штуками).

Function startSession () (// Якщо сесія вже була запущена, припиняємо виконання і повертаємо TRUE // (параметр session.auto_start в файлі налаштувань php.ini повинен бути вимкнений - значення за замовчуванням) if (session_id ()) return true; else return session_start (); // Примітка: до версії 5.3.0 функція session_start () повертала TRUE навіть в разі помилки. // Якщо ви використовуєте версію нижче 5.3.0, виконуйте додаткову перевірку session_id () // після виклику session_start ()) function destroySession () (if (session_id ()) (// Якщо є активна сесія, видаляємо куки сесії, setcookie (session_name (), session_id (), time () - 60 * 60 * 24); // і знищуємо сесію session_unset ( ); session_destroy ();))

Примітка: Мається на увазі, що базові знання про сесіях PHP у читача є, тому принцип роботи функцій session_start () і session_destroy () висвітлювати тут не будемо. Завдання верстки форми входу і аутентифікації користувача не відносяться до теми статті, тому їх ми також опустимо. Нагадаю тільки, що для ідентифікації користувача в кожному наступному запиті, нам необхідно в момент успішного входу зберегти в сесійному змінної (з ім'ям userid, наприклад) ідентифікатор користувача, який буде доступний у всіх наступних запитах в межах життя сесії. Також необхідно реалізувати обробку результату нашої функції startSession (). Якщо функція повернула FALSE - відобразити в браузері форму входу. Якщо функція повернула TRUE, і сесійний змінна, що містить ідентифікатор авторизованого користувача (в нашому випадку - userid), існує - відобразити сторінку авторизованого користувача (докладніше про обробку помилок см. Додаток від 2013-06-07 в розділі про сесійних змінних).

Поки все зрозуміло. Питання починаються, коли потрібно реалізувати контроль відсутності активності користувача (session timeout), дати можливість одночасної роботи в одному браузері декількох користувачів, а також захистити сесії від несанкціонованого використання. Про це і піде мова нижче.

Контроль відсутності активності користувача вбудованими засобами PHP

Перше питання, яке часто виникає у розробників всіляких консолей для користувачів - автоматичне завершення сеансу в разі відсутності активності з боку користувача. Немає нічого простішого, ніж зробити це за допомогою вбудованих можливостей PHP. (Цей варіант не відрізняється особливою надійністю і гнучкістю, але розглянемо його для повноти картини).

Function startSession () (// Таймаут відсутності активності користувача (в секундах) $ sessionLifetime \u003d 300; if (session_id ()) return true; // Встановлюємо час життя куки ini_set ( "session.cookie_lifetime", $ sessionLifetime); // Якщо таймаут відсутності активності користувача заданий, встановлюємо час життя сесії на сервері // Примітка: Для production-сервера рекомендується попередньо встановити ці параметри у файлі 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;)

Трохи пояснень. Як відомо, PHP визначає, яку саме сесію потрібно запустити, на ім'я куки, переданому браузером в заголовку запиту. Браузер ж, в свою чергу, отримує цей куки від сервера, куди поміщає його функція session_start (). Якщо час життя куки в браузері минув, він не буде переданий в запиті, а значить PHP не зможе визначити, яку сесію потрібно запустити, і розцінить це як створення нової сесії. Параметр налаштувань PHP session.gc_maxlifetime, який встановлюється рівним нашому таймаут відсутності активності користувача, задає час життя PHP-сесії і контролюється сервером. Працює контроль часу життя сесії наступним чином (тут розглядається приклад сховища сесій в тимчасових файлах як найпоширеніший і встановлений за замовчуванням в PHP варіант).

У момент створення нової сесії в каталозі, встановленому як каталог для зберігання сесій в параметрі налаштувань PHP session.save_path, створюється файл з ім'ям sess_ , де - ідентифікатор сесії. Далі, в кожному запиті, в момент запуску вже існуючої сесії, PHP оновлює час модифікації цього файлу. Таким чином, в кожному наступному запиті PHP, шляхом різниці між поточним часом і часом останньої модифікації файлу сесії, може визначити, чи є сесія активної, або її час життя вже минув. (Механізм видалення старих файлів сесій більш детально розглядається в наступному розділі).

Примітка: Тут слід зазначити, що параметр session.gc_maxlifetime діє на всі сесії в межах одного сервера (точніше, в межах одного головного процесу PHP). На практиці це означає, що якщо на сервері працює кілька сайтів, і кожен з них має власний таймаут відсутності активності користувачів, то установка цього параметра на одному з сайтів призведе до його встановлення і для інших сайтів. Те ж стосується і shared-хостингу. Для уникнення подібної ситуації використовуються окремі каталоги сесій для кожного сайту в межах одного сервера. Установка шляху до каталогу сесій проводиться за допомогою параметра session.save_path в файлі налаштувань php.ini, або шляхом виклику функції ini_set (). Після цього сесії кожного сайту будуть зберігатися в окремих каталогах, і параметр session.gc_maxlifetime, встановлений на одному з сайтів, буде діяти тільки на сесії міської ради. Ми не станемо розглядати цей випадок детально, тим більше, що у нас в запасі є більш гнучкий варіант контролю відсутності активності користувача.

Контроль відсутності активності користувача за допомогою сесійних змінних

Здавалося б, попередній варіант при всій своїй простоті (всього пару додаткових рядків коду) дає всі, що нам потрібно. Але що, якщо не кожен запит можна розцінювати як результат активності користувача? Наприклад, на сторінці встановлений таймер, який періодично виконує AJAX-запит на отримання оновлень від сервера. Такий запит можна розцінювати як активність користувача, а значить автоматичне продовження часу життя сесії є не коректним в даному випадку. Але ми знаємо, що PHP оновлює час модифікації файлу сесії автоматично при кожному виклику функції session_start (), а значить будь-який запит призведе до продовження часу життя сесії, і таймаут відсутності активності користувача не настане ніколи. До того ж, остання примітка з попереднього розділу про тонкощі роботи параметра session.gc_maxlifetime може здатися комусь занадто заплутаним і складним в реалізації.

Для вирішення цієї проблеми відмовимося від використання вбудованих механізмів PHP і введемо кілька нових сесійних змінних, які дозволять нам контролювати час відсутності активності користувачів самостійно.

Function startSession ($ isUserActivity \u003d true) ($ sessionLifetime \u003d 300; if (session_id ()) return true; // Встановлюємо час життя куки до закриття браузера (контролювати всі будемо на стороні сервера) ini_set ( "session.cookie_lifetime", 0) ; if (! session_start ()) return false; $ t \u003d time (); if ($ sessionLifetime) (// Якщо таймаут відсутності активності користувача заданий, // перевіряємо час, що минув з моменту останньої активності користувача // (час останнього запиту , коли була оновлена \u200b\u200bсесійний змінна lastactivity) if (isset ($ _ SESSION [ "lastactivity"]) && $ t - $ _ SESSION [ "lastactivity"]\u003e \u003d $ sessionLifetime) (// Якщо час, що минув з моменту останньої активності користувача, / / більше таймаута відсутності активності, значить сесія закінчилася, і потрібно завершити сеанс destroySession (); return false;) else (// якщо таймаут ще не настав, // і якщо запит прийшов як результат активності користувача, // оновлюємо змінну lastactivity значенням поточного вр Ємен, // продовжуючи тим самим час сеансу ще на sessionLifetime секунд if ($ isUserActivity) $ _SESSION [ "lastactivity"] \u003d $ t; )) Return true; )

Підсумуємо. У кожному запиті ми перевіряємо, чи не досягнуть таймаут з моменту останньої активності користувача до поточного моменту, і якщо він досягнутий - знищуємо сесію і перериваємо виконання функції, повертаючи FALSE. Якщо ж таймаут не досягнуть, і в функцію переданий параметр $ isUserActivity зі значенням TRUE - оновлюємо час останньої активності користувача. Все, що нам залишається зробити - це визначати в зухвалій скрипті, чи є запит результатом активності користувача, і якщо немає - викликати функцію startSession зі значенням параметра $ isUserActivity, рівним FALSE.

Доповнення від 2013-06-07
Обробка результату функції sessionStart ()

У коментарях звернули увагу на те, що повернення FALSE не дає повного розуміння причини помилки, і це абсолютно справедливо. Я не став публікувати тут детальну обробку помилок (обсяг статті і так не маленький), оскільки це не належить безпосередньо до теми статті. Але з огляду на коментарі, внесу ясність.

Як видно, функція sessionStart може повернути FALSE в двох випадках. Або сесію не вдалося запустити через якихось внутрішніх помилок сервера (наприклад, неправильні настройки сесій в php.ini), або час життя сесії минув. У першому випадку ми повинні перекинути користувача на сторінку з помилкою про те, що є проблеми на сервері, і формою звернення в службу підтримки. У другому випадку ми повинні перевести користувача на форму входу і вивести в ній відповідне повідомлення про те, що час сесії минув. Для цього нам необхідно ввести коди помилок і повертати замість FALSE відповідний код, а в зухвалій методі перевіряти його і діяти відповідним чином.

Тепер, навіть якщо сесія на сервері як і раніше існує, вона буде знищена при першому ж зверненні до неї, якщо таймаут відсутності активності користувача закінчився. І це станеться незалежно від того, який час життя сесій встановлено в глобальних налаштуваннях PHP.

Примітка: А що станеться, якщо браузер був закритий, і куки з ім'ям сесії був автоматично знищений? Запит до сервера під час наступного відкривання браузера не буде містити куки сесії, і сервер не зможе відкрити сесію і перевірити таймаут відсутності активності користувача. Для нас це рівносильно створенню нової сесії і ніяк не впливає на функціонал і безпеку. Але виникає справедливе запитання - а хто ж тоді знищить стару сесію, якщо до сих пір її знищували ми після закінчення часу очікування? Або вона тепер буде висіти в каталозі сесій вічно? Для очищення старих сесій в PHP існує механізм під назвою garbage collection. Він запускається в момент чергового запиту до сервера і чистить все старі сесії на підставі дати останньої зміни файлів сесій. Але запуск механізму garbage collection відбувається не при кожному запиті до сервера. Частота (а точніше, ймовірність) запуску визначається двома параметрами налаштувань session.gc_probability і session.gc_divisor. Результат від ділення першого параметра на другий і є ймовірністю запуску механізму garbage collection. Таким чином, для того, щоб механізм очищення сесій запускався при кожному запиті до севреру, ці параметри потрібно встановити в рівні значення, наприклад «1». Такий підхід гарантує чистоту каталогу сесій, але, очевидно, є занадто накладним для сервера. Тому в production-системах за замовчуванням встановлюється значення session.gc_divisor, дорівнює 1000, що означає, що механізм garbage collection буде запускатися з ймовірністю 1/1000. Якщо ви поексперіментіруете з цими настройками в своєму файлі php.ini, то зможете помітити, що в описаному вище випадку, коли браузер закривається і очищає всі свої куки, в каталозі сесій якийсь час все ще залишаються старі сесії. Але це не повинно вас хвилювати, тому що як вже було сказано, це жодним чином не впливає на безпеку нашого механізму.

Доповнення від 2013-06-07

Запобігання зависання скриптів через блокування файлу сесії

У коментарях підняли питання про зависання одночасно виконуються скриптів через блокування файлу сесії (як найяскравіший варіант - long poll).

Для початку зазначу, що ця проблема безпосередньо не залежить від завантаженості сервера або кількості користувачів. Звичайно, чим більше запитів, тим повільніше виконуються скрипти. Але це коссвенная залежність. Проблема з'являється тільки в межах однієї сесії, коли сервера приходить кілька запитів від імені одного користувача (наприклад, один з них long poll, а решта - звичайні запити). Кожен запит намагається отримати доступ до одного і того ж файлу сесії, і якщо попередній клопотання не розблокував файл, то наступний буде висіти в очікуванні.

Для відомості блокування файлів сесій до мінімуму настійно рекомендується закривати сесію шляхом виклику функції session_write_close () відразу після того, як виконані всі дії з сесійними змінними. На практиці це означає, що не слід зберігати в сесійних змінних все підряд і звертатися до них на всьому протязі виконання скрипта. А якщо і треба зберігати в сесійних змінних якісь робочі дані, то зчитувати їх відразу при старті сесії, зберігати в локальні змінні для подальшого використання і закривати сесію (мається на увазі закриття сесії за допомогою функції session_write_close, а не знищення за допомогою session_destroy).

У нашому прикладі це означає, що відразу після відкриття сесії, перевірки часу її життя та існування авторизованого користувача, ми повинні вважати і зберегти всі додаткові необхідні додатком сесійні змінні (якщо такі існують), після чого закрити сесію за допомогою виклику session_write_close () і продовжити виконання скрипта, будь то long poll або звичайний запит.

Захист сесій від несанкціонованого використання

Уявімо собі ситуацію. Один з ваших користувачів чіпляє троян, який грабує куки браузера (в якому зберігається наша сесія) і відправляє його на вказаний email. Зловмисник отримує куки і використовує його для підробки запиту від імені нашого авторизованого користувача. Сервер успішно приймає і обробляє цей запит, як якби він прийшов від авторизованого користувача. Якщо не реалізована додаткова перевірка IP-адреси, така атака призведе до успішного злому аккаунта користувача з усіма наслідками, що випливають.

Чому це стало можливим? Очевидно, тому що ім'я та ідентифікатор сесії завжди одні й ті ж на весь час життя сесії, і якщо отримати ці дані, то можна безперешкодно слати запити від імені іншого користувача (природно, в межах часу життя цієї сесії). Можливо, це не найпоширеніший вид атак, але теоретично все виглядає цілком реалізованим, особливо з огляду на, що подібного трояни навіть не потрібні права адміністратора, щоб грабувати куки браузера користувача.

Як же можна захиститися від атак подібного роду? Знову-таки, очевидно, обмеживши час життя ідентифікатора сесії і періодично змінюючи ідентифікатор в межах однієї сесії. Ми можемо також змінювати і ім'я сесії, повністю видаляючи стару і створюючи нову сесію, копіюючи в неї все сесійні змінні зі старої. Але на суть підходу це не впливає, тому для простоти обмежимося тільки ідентифікатором сесії.

Зрозуміло, що чим менше час життя ідентифікатора сесії, тим менше буде часу у зловмисника, щоб отримати і застосувати куки для підробки запиту користувача. В ідеальному випадку для кожного запиту повинен використовуватися новий ідентифікатор, що дозволить звести до мінімуму можливість використання чужої сесії. Але ми розглянемо загальний випадок, коли час регенерації ідентифікатора сесії встановлюється довільно.

(Не будемо про ту частину коду, яка вже розглянута).

Function startSession ($ isUserActivity \u003d true) (// Час життя ідентифікатора сесії $ idLifetime \u003d 60; ... if ($ idLifetime) (// Якщо час життя ідентифікатора сесії задано, // перевіряємо час, що минув з моменту створення сесії або останньої регенерації // (час останнього запиту, коли була оновлена \u200b\u200bсесійний змінна starttime) 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;)

Отже, при створенні нової сесії (яке відбувається в момент успішного входу користувача), ми встановлюємо сесійний змінну starttime, що зберігає для нас час останньої генерації ідентифікатора сесії, в значення, рівне поточного часу сервера. Далі в кожному запиті ми перевіряємо, чи не пройшло чи достатньо часу (idLifetime) з моменту останньої генерації ідентифікатора, і якщо минуло - генеруємо новий. Таким чином, якщо протягом встановленого часу життя ідентифікатора зловмисник, який отримав куки авторизованого користувача, не встигне їм скористатися, підроблений запит буде розцінений сервером як неавторизований, і зловмисник потрапить на сторінку входу.

Примітка: Новий ідентифікатор сесії потрапляє в куки браузера при виконанні функції session_regenerate_id (), яка відправляє новий куки, аналогічно функції session_start (), тому нам немає необхідності оновлювати куки самостійно.

Якщо ми хочемо максимально убезпечити наші сесії, досить встановити час життя ідентифікатора в одиницю або ж взагалі винести функцію session_regenerate_id () за дужки і прибрати всі перевірки, що призведе до регенерації ідентифікатора в кожному запиті. (Я не перевіряв вплив такого підходу на швидкодію, і можу тільки сказати, що функція session_regenerate_id (true) виконує по суті всього 4 дії: генерація нового ідентифікатора, створення заголовка з куки сесії, видалення старого і створення нового файлу сесії).

Ліричний відступ: Якщо троян виявиться настільки розумним, що не відправлятиме куки зловмисникові, а сам організовує відправку заздалегідь підготовленого підробленого запиту відразу при отриманні куки, описаний вище метод, швидше за все, не зможе захистити від подібної атаки, тому що між часом отримання трояном куки і відправкою підробленого запиту практично не буде різниці, і велика ймовірність, що в цей момент не відбудеться регенерації ідентифікатора сесії.

Можливість одночасної роботи в одному браузері від імені кількох користувачів

Останнє завдання, яку хотілося б розглянути - можливість одночасної роботи в одному браузері декількох користувачів. Ця можливість особливо корисна на етапі тестування, коли потрібно емулювати одночасну роботу користувачів, і бажано робити це в своєму улюбленому браузері, а не використовувати весь доступний арсенал або відкривати кілька примірників браузера в режимі «інкогніто».

У наших попередніх прикладах ми не задавали явно ім'я сесії, тому використовувалося ім'я, встановлене в PHP за замовчуванням (PHPSESSID). Це означає, що всі сесії, які створювалися нами досі, відправляли браузеру куки під ім'ям PHPSESSID. Очевидно, що якщо ім'я куки завжди однакове, то немає можливості в межах одного браузера організувати дві сесії з однаковим ім'ям. Але якби ми для кожного користувача використовували власне ім'я сесії, то проблема була б вирішена. Так і зробимо.

Function startSession ($ isUserActivity \u003d true, $ prefix \u003d null) (... if (session_id ()) return true; // Якщо в параметрах переданий префікс користувача, // встановлюємо унікальне ім'я сесії, що включає цей префікс, // інакше встановлюємо загальне для всіх користувачів ім'я (наприклад, MYPROJECT) session_name ( "MYPROJECT". ($ prefix? "_". $ prefix: "")); ini_set ( "session.cookie_lifetime", 0); if (! session_start ()) return false; ...)

Тепер залишилося подбати про те, щоб викликає скрипт передавав в функцію startSession () унікальний префікс для кожного користувача. Це можна зробити, наприклад, через передачу префікса в GET / POST параметрах кожного запиту або через додатковий куки.

висновок

На закінчення приведу повний кінцевий код наших функцій для роботи з сесіями PHP, Що включає всі розглянуті вище завдання.

Function 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) (destroySession (); 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 destroySession () (if (session_id ()) (session_unset (); setcookie (session_name (), session_id (), time () -60 * 60 * 24); session_destroy ();))

Сподіваюся, ця стаття заощадить трохи часу тим, хто ніколи особливо не заглиблювався в механізм сесій, і дасть достатньо розуміння цього механізму тим, хто тільки починає знайомитися з PHP.

.
У цій статті ми додамо до нашої реєстрації перевіркуe- mailадреси, автоматичний вхід і відновлення забутого пароля . Перш ніж приступати до виконання уроку, переконайтеся, що у Вас на сервері працює функція mail ().

Почнемо з додавання полів в таблицю « users» . Нам потрібно поле для зберігання e-mail адреси, поле для стану користувача (0 - Неактивована, 1 - активований) і поле з датою реєстрації.





Потім потрібно підправити save_user.php, Додавши перевірку на коректність e-mail адреси і відправлення листа для підтвердження реєстрації. У листі знаходиться посилання з двома змінними, що передаються методом get: логін і згенерований, унікальний для кожного користувача, код. Код нам потрібен, щоб користувач не зміг активувати свій аккаунт без листи, а це дасть нам впевненість, що зазначену адресу пошти, дійсно, належить йому. Додамо наступний код, після вилучення з глобальних змінних відправлених даних:

If (isset ($ _ POST [ "email"])) ($ email \u003d $ _POST [ "email"]; if ($ email \u003d\u003d "") (unset ($ email);))
if (empty ($ login) or empty ($ password) or empty ($ code) or empty ($ email))
// додамо змінну зe- mailадресою
// якщо користувач не ввів логін або пароль, то видаємо помилку і зупиняємо скрипт
{
exit ( "Ви ввели не всю інформацію, поверніться назад і заповніть всі поля!"); // зупиняємо виконання сценаріїв
}
if (! preg_match ( "/ [Email protected]+ \\. (2,3) / i ", $ email)) // перевірка е-mail адреси регулярними виразами на коректність
(Exit ( "Невірно введений е-mail!");)

У запиті додавання нового користувача необхідно дописати і дату реєстрації. Якщо в базу вдало вставлені дані і користувач зареєстрований, то потрібно відправити повідомлення на введений адреса:

// якщо такого немає, то зберігаємо дані
$ Result2 \u003d mysql_query ( "INSERT INTO users (login, password, avatar, email, date) VALUES (" $ login "," $ password "," $ avatar "," $ email ", NOW ())");
// Перевіряємо, чи є помилки
if ($ result2 \u003d\u003d "TRUE")
{
$ Result3 \u003d mysql_query ( "SELECT id FROM users WHERE login \u003d" $ login "", $ db); // витягаємо ідентифікатор користувача. Завдяки йому у нас і буде унікальний код активації, адже двох однакових ідентифікаторів бути не може.
$ Myrow3 \u003d mysql_fetch_array ($ result3);
$ Activation \u003d md5 ($ myrow3 [ "id"]). Md5 ($ login); // кодактиваціїаккаунта. Зашифруємо через функцію md5 ідентифікатор і логін. Таке поєднання користувач навряд чи зможе підібрати вручну через адресний рядок.
$ Subject \u003d "Підтвердження реєстрації"; //Тема повідомлення
$ Message \u003d "Привіт! Дякую за реєстрацію на citename.ru \\ nВаш логін:". $ Login. "\\ N
Перейдіть по посиланню, щоб активувати ваш аккаунт: \\ nhttp: //localhost/test3/activation.php? Login \u003d ". $ Login." & Code \u003d ". $ Activation." \\ NС повагою, \\ n
Адміністрація citename.ru "; // зміст повідомлення
mail ($ email, $ subject, $ message, "Content-type: text / plane; Charset \u003d windows-1251 \\ r \\ n"); // відправляємо повідомлення

Echo "Вам на E-mail надіслано листа з власний кореспондент, для підтвердження реєстрації. Увага! Посилання дійсне 1 годину. Головна сторінка"; // говоримо про відправленому листі користувачеві
}

Повідомлення надіслано! Тепер користувач відкриє його і перейде за вказаним URL на сторінку, яка буде перевіряти код активації. Переконавшись, що код вірний, ми підтверджуємо реєстрацію, змінюючи в базі значення поля activation з «0» на «1».

створюємо файл activation.php

include ( "bd.php"); // файлbd. php повинен бути в тій же папці, що і всі інші, якщо це не так, то просто змініть шлях
$ Result4 \u003d mysql_query ( "SELECT avatar FROM users WHERE activation \u003d" 0 "AND UNIX_TIMESTAMP () - UNIX_TIMESTAMP (date)\u003e 3600"); // витягаємо аватарки тих користувачів, які протягом години не активували свій аккаунт. Отже їх треба видалити з бази, а так само і файли їх аватарок
if (mysql_num_rows ($ result4)\u003e 0) (
$ Myrow4 \u003d mysql_fetch_array ($ result4);
do
{
// видаляємо аватари в циклі, якщо вони не стандартні
if ($ myrow4 [ "avatar"] \u003d\u003d "avatars / net-avatara.jpg") ($ a \u003d "Нічого не робити";)
else (
unlink ($ myrow4 [ "avatar"]); // видаляємо файл
}
}
while ($ myrow4 \u003d mysql_fetch_array ($ result4));
}
mysql_query ( "DELETE FROM users WHERE activation \u003d" 0 "AND UNIX_TIMESTAMP () - UNIX_TIMESTAMP (date)\u003e 3600"); // видаляємо користувачів з бази
if (isset ($ _ GET [ "code"])) ($ code \u003d $ _ GET [ "code"];) //код підтвердження
else
(Exit ( "Ви зайшли на сторінку без коду підтвердження!");) // якщо не вказалиcode, То видаємо помилку
if (isset ($ _ GET [ "login"])) ($ login \u003d $ _ GET [ "login"];) // логін, який потрібно активувати
else
(Exit ( "Ви зайшли на сторінку без логіна!");) // якщо не вказали логін, то видаємо помилку
$ Result \u003d mysql_query ( "SELECT id FROM users WHERE login \u003d" $ login "", $ db); // витягаємо ідентифікатор користувача з даним логіном
$ Activation \u003d md5 ($ myrow [ "id"]). Md5 ($ login); // створюємо такий же код підтвердження
if ($ activation \u003d\u003d $ code) ( // порівнюємо отриманий зurl і згенерований код
mysql_query ( "UPDATE users SET activation \u003d" 1 "WHERE login \u003d" $ login "", $ db); // якщо рівні, то активуємо користувача
echo "Ваш Е-мейл підтверджений! Тепер ви можете зайти на сайт під своїм логіном! Головна сторінка";
}
else (echo "Помилка! Ваш Е-мейл не підтверджений! Головна сторінка";
// якщо ж отриманий зurl і згенерований код не рівні, то видаємо помилку
}
?>

E-mail адресу підтверджено, тепер ми знаємо, що ця адреса належить даному користувачеві, На нього можна буде послати пароль, якщо користувач його забуде, або інші повідомлення. Але в чому відмінність активованих користувачів, від неактивованих? І ті й інші можуть зайти на сайт, отже, нам потрібно обмежити в доступі неактивованих. відкриємо файл testreg. php і допишемо ще одна умова в запиті до бази:

$ Result \u003d mysql_query ( "SELECT * FROM users WHERE login \u003d" $ login "AND password \u003d" $ password "AND activation \u003d" 1 "", $ db); // витягаємо з бази всі дані про користувача з введеним логіном
// ми дописали «ANDactivation\u003d "1" », тобто користувач буде шукатися тільки серед активованих. Бажано додати цю умову до інших подібних перевірок даних користувача

Якщо користувач забуде пароль, то для такого випадку потрібно вивести посилання на головній сторінці, По якій він зможе його відновити, а так само можна відразу поставити чекбокс для автоматичного входу.

Запам'ятати мене з цього.






зареєструватися


Забули пароль?

Посилання є, а файлу немає. Давайте ж напишемо send_ pass. php. У ньому ми запитаємо у користувача логін і адреса пошти. Якщо введений e-mail і логін є в базі, то відправимо на нього новий пароль, Якщо користувач забув старий, адже ми переконалися при реєстрації, що адреса електронної пошти дійсний.

if (isset ($ _ POST [ "login"])) ($ login \u003d $ _POST [ "login"]; if ($ login \u003d\u003d "") (unset ($ login);)) // заносимо самі ввели логін в змінну $ login, якщо він порожній, то знищуємо змінну
if (isset ($ _ POST [ "email"])) ($ email \u003d $ _POST [ "email"]; if ($ email \u003d\u003d "") (unset ($ email);)) // заносимо самі ввели e-mail, якщо він порожній, то знищуємо змінну
if (isset ($ login) and isset ($ email)) ( // якщо існують необхідні змінні

Include ( "bd.php");

$ Result \u003d mysql_query ( "SELECT id FROM users WHERE login \u003d" $ login "AND email \u003d" $ email "AND activation \u003d" 1 "", $ db); // такийчиукористувачае- мейл
$ Myrow \u003d mysql_fetch_array ($ result);
if (empty ($ myrow [ "id"]) or $ myrow [ "id"] \u003d\u003d "") (
// якщо активованого користувача з таким іменем і е-mail адресою немає
exit ( "Користувача з таким e-mail адресою не виявлено ні в одній базі ЦРУ :) Головна сторінка");
}
// якщо користувач з таким іменем і е-мейлом знайдений, то необхідно згенерувати для нього випадковий пароль, оновити його в базі і відправити на е-мейл
$ Datenow \u003d date ( "YmdHis"); // витягаємо дату
$ New_password \u003d md5 ($ datenow); // шифруємо дату
$ New_password \u003d substr ($ new_password, 2, 6); // витягаємо з шифру 6 символів починаючи з другого. Це і буде наш випадковий пароль. Далі запишемо його в базу, зашифрувавши точно так же, як і зазвичай.

$ New_password_sh \u003d strrev (md5 ($ new_password)). "B3p6f"; // зашифрували
mysql_query ( "UPDATE users SET password \u003d" $ new_password_sh "WHERE login \u003d" $ login "", $ db); // оновиливбазі
// формуємо повідомлення

$ Message \u003d "Привіт,". $ Login. "! Ми сгененріоровалі для Вас пароль, тепер Ви зможете увійти на сайт citename.ru, використовуючи його. Після входу бажано його змінити. Пароль: \\ n". $ New_password; //Текст повідомлення
mail ($ email, "Відновлення пароля", $ message, "Content-type: text / plane; Charset \u003d windows-1251 \\ r \\ n"); // відправляємоповідомлення

Echo " На Ваш e-mail відправлено лист з паролем. Ви будете переміщені через 5 сек. Якщо не хочете чекати, то натисніть сюди. "; // перенаправляємо користувача
}
else ( // якщо дані ще не введені
echo "


Забули пароль?


Забули пароль?



Введіть ваш логін:



Введіть Ваш E-mail:






";
}
?>

Далі ми зробимо автоматичний вхід. Працювати він буде так: при вдалому вході з натиснутим чекбоксів в cookie буде вписуватися auto \u003d "yes". Якщо сервер побачить, що в браузері auto \u003d "yes", то запустить сесію, а змінні візьме там же, в cookie. Потім йде перевірка запущених сесій по базі.

відкриємо testreg. php і допишемо після вдалого входу код:

If (isset ($ _ POST [ "save"])) (
// Якщо користувач хоче, щоб його дані збереглися для подальшого входу, то зберігаємо в куках його браузера

setcookie ( "id", $ myrow [ "id"], time () + 9999999);)
if (isset ($ _ POST [ "autovhod"])) (
// Якщо користувач хоче входити на сайт автоматично
setcookie ( "auto", "yes", time () + 9999999);
setcookie ( "login", $ _POST [ "login"], time () + 9999999);
setcookie ( "password", $ _POST [ "password"], time () + 9999999);
setcookie ( "id", $ myrow [ "id"], time () + 9999999);)

Тепер треба запустити в потрібному місці сесію, якщо стоїть автоматичний вхід. відкриємо index.php і напишемо на самому початку сторінки:

// вся процедура працює на сесіях. Саме в ній зберігаються дані користувача, поки він знаходиться на сайті. Дуже важливо запустити їх на самому початку сторінки !!!
session_start ();
include ( "bd.php"); // файл bd.php повинен бути в тій же папці, що і всі інші, якщо це не так, то просто змініть шлях
if (isset ($ _ COOKIE [ "auto"]) and isset ($ _ COOKIE [ "login"]) and isset ($ _ COOKIE [ "password"]))
{// якщо є необхідні змінні
if ($ _COOKIE [ "auto"] \u003d\u003d "yes") ( // якщо користувач бажає входити автоматично, то запускаємо сесії
$ _SESSION [ "password"] \u003d strrev (md5 ($ _ COOKIE [ "password"])). "B3p6f"; // в куках пароль не була зашифрований, а в сесіях зазвичай зберігаємо зашифрований
$ _SESSION [ "login"] \u003d $ _ COOKIE [ "login"]; // сесіязлогіном
$ _SESSION [ "id"] \u003d $ _ COOKIE [ "id"]; // ідентифікатор користувача
}
}

Ось тепер нам навіть вихід не допоможе, що б змінити користувача! В exit. php видаляються сесії, які все одно створюються на index. php, Завдяки cookie, які зберігаються дуже довго! Давайте вже все-таки полагодимо файл exit. php, А то він не функціональний в разі автоматичного входу. Треба всього лише очистити в cookie автоматичний вхід, після видалення змінних з сесії:

Setcookie ( "auto", "", time () + 9999999); // очищаємо автоматичний вхід

Так само необхідно додати в update_ user. php після поновлення логіна в сесії:

$ _SESSION [ "login"] \u003d $ login; // Оновлюємо логін в сесії
if (isset ($ _ COOKIE [ "login"])) (
setcookie ( "login", $ login, time () + 9999999); // оновлюємологінвкуках
}

І те ж саме з паролем

$ Result4 \u003d mysql_query ( "UPDATE users SET password \u003d" $ password "WHERE login \u003d" $ old_login "", $ db); // оновлюємопароль
if ($ result4 \u003d\u003d "TRUE") ( // якщо вірно, то оновлюємо його в сесії
$ _SESSION [ "password"] \u003d $ password;
if (isset ($ _ COOKIE [ "password"])) (
setcookie ( "password", $ _ POST [ "password"], time () + 9999999); // оновлюємопарольвкуках, якщовониє
}

Ну от і все. Сподіваюся, що у Вас все вийде! Успіхів!

Доброго времени суток друзі! Давай з Вами розглянемо реєстрацію користувачів на PHP. Для початку давайте визначимо умови для нашої реєстрації користувачів:

  • Пароль шифруємо за допомогою алгоритму MD5
  • Пароль будемо "солити"
  • Перевірка на зайнятість Логіна
  • Активація користувача листом.
  • Запис і зберігання даних в СУБД MySQL

Для написання даного скрипта нам потрібно зрозуміти, що таке реєстрація користувача. Реєстрація користувача - це отримання даних реального користувача, обробка та зберігання даних.

Якщо пояснювати простими словами то реєстрація це всього лише запис і зберігання певних даних за якими ми можемо авторизувати користувача в нашому випадку - це Логін і Пароль.

Авторизація - надання певній особі або групі осіб прав на виконання певних дій, а також процес перевірки даних прав при спробі виконання цих дій. Проше кажучи за допомогою авторизації ми можемо розмежувати доступ до того чи іншого контенту на нашому сайті.

Розглянемо структуру каталогів скриптів для реалізації нашої реєстрації з авторизацією. Нам потрібно розбити скрипти на логічні складові. Модулі реєстрації та авторизації ми помістивши в окремий каталог. Так само в окремі каталоги ми помістимо підключення до бази даних MySQL, Файл з одними функціями, файл стилів CSS і наш шаблон HTML. Дана структура дозволяє швидко орієнтуватися в скриптах. Уявіть собі, що у Вас великий сайт з купою модулями і т.д. і якщо не буде порядку, то буде дуже складно щось відшукати в такому бардаку.

Так як ми будемо зберігати всі дані в СУБД MySQL, То давайте створимо не більшу таблицю в якій будемо зберігати дані про реєстрацію.

Для початку потрібно створити таблицю в базі даних. таблицю назвемо bez_reg де bez - це префікс таблиці, а reg назва таблиці.

Структура таблиці: bez_reg

- - Структура таблиці `bez_reg` - CREATE TABLE IF NOT EXISTS` 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;

Тепер створимо основні скрипти для подальшої роботи.

файл INDEX.PHP

файл CONFIG.PHP

"); ?>

файл 404.HTML

Помилка 404

Помилка 404

На сторінці сталася помилка 404

повернутися

файл BD.PHP

файл INDEX.HTML

Реєстрація користувачів PHP MySQL з активацією листом

файл 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;) / ** Проста обгортка для запитів до MySQL * @param string $ sql * / function mysqlQuery ($ sql) ($ res \u003d mysql_query ($ sql); / * Перевіряємо результат Це показує реальний запит, надісланий до MySQL, а також помилку. Зручно при налагодженні. * / if (! $ res) ($ message \u003d "Невірний запит:". mysql_error (). "\\ n"; $ message. \u003d "запит цілком : ". $ sql; die ($ message);) return $ res;) / ** Простий генератор солі * @param string $ sql * / function salt () ($ salt \u003d substr (md5 (uniqid ()), - 8); return $ salt;)

    Давайте приступимо до написання реєстрації. Для початку нам потрібно буде зробити шаблон форми реєстрації, щоб користувач зміг внести свої дані для обробки. Далі нам потрібно буде написати сам обробник форми, який перевірить на коректність введені дані користувача. Після того як дані успішно перевірені записуємо їх в нашу базу даних і відправляємо лист користувачеві для активації його облікового запису.

    файл REG.PHP

    Ви успішно зареєструвалися! Будь ласка активуйте свій аккаунт !!"; // Виробляємо активацію облікового запису if (isset ($ _ GET [" key "])) (// Перевіряємо ключ $ 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" Ключ активації не вірний! "; // Перевіряємо наявність помилок і виводимо користувачеві if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Отримуємо адреса користувача $ row \u003d mysql_fetch_assoc ($ res); $ email \u003d $ row [ "login"]; // Активуємо аккаунт користувача $ sql \u003d "UPDATE` ". BEZ_DBPREFIX." reg` SET `status` \u003d 1 WHERE` login` \u003d "". $ email. "" "; $ res \u003d mysqlQuery ($ sql); // Відправляємо лист для активації $ title \u003d "(! LANG: Ваш аккаунт на http: // сайт успішно активований"; $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 protected](+ \\.) + (2,6) $ / i ", $ _POST [" email "])) $ err \u003d" Неможливо правильно введений E-mail "." \\ N ";) if (empty ($ _ POST [ "pass"])) $ err \u003d "Поле Пароль не може бути порожнім"; if (empty ($ _ POST [ "pass2"])) $ err \u003d "Поле Підтвердження пароля не може бути порожнім"; // Перевіряємо наявність помилок і виводимо користувачеві if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Продовжуємо перевіряти введені дані Перевіряємо на совподеніе паролі * / if ($ _ POST [ "pass"]! \u003d $ _POST [ "pass2" ]) $ err \u003d "Паролі не совподает"; // Перевіряємо наявність помилок і виводимо користувачеві if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (/ * Перевіряємо чи існує у нас такий користувач в БД * / $ 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 "На жаль Логін: ". $ _POST [" email "]." зайнятий! "; // Перевіряємо наявність помилок і виводимо користувачеві if (count ($ err)\u003e 0) echo showErrorMessage ($ err); else (// Отримуємо хеш солі $ salt \u003d salt (); // Солимо пароль $ pass \u003d md5 (md5 ($ _ POST [ "pass"]). $ salt); / * Якщо все добре, пишемо дані в базу * / $ sql \u003d "INSERT INTO` ". BEZ_DBPREFIX." reg` VALUES ( "", "" . escape_str ($ _ POST [ "email"]). "", "". $ pass. "", "". $ salt. "", "". md5 ($ salt). "", 0) "; $ res \u003d mysqlQuery ($ sql); // Відправляємо лист для активації $ url \u003d BEZ_HOST. "less / reg /? mode \u003d reg & key \u003d". md5 ($ salt); $ title \u003d "(! LANG: Реєстрація на http: / / сайт"; $message = "Для активации Вашего акаунта пройдите по ссылке ". $url .""; sendMessageMail($_POST["email"], BEZ_MAIL_AUTOR, $title, $message); //Сбрасываем параметры header("Location:". BEZ_HOST ."less/reg/?mode=reg&status=ok"); exit; } } } } ?>!}

    файл REG_FORM.HTML

    Реєстрація користувачів PHP MySQL з активацією листом

    E-mail *:
    пароль *:
    підтвердження пароля *:

    Поля зі значком * обов'язкові для заповнення

    Так як реєстрація користувачів у нас готова, саме час написати авторизацію. Створимо форму для авторизації користувачів, далі напишемо обробник форми авторизації і на останок зробимо скрипт show.php який буде показувати нам авторизовані ми в системі чи ні.

    файл AUTH.PHP

    0) echo showErrorMessage ($ err); else (/ * Створюємо запит на вибірку з бази даних для перевірки достовірності користувача * / $ sql \u003d "SELECT * FROM` ". BEZ_DBPREFIX." reg` WHERE `login` \u003d" ". escape_str ($ _ POST [" email "]) . "" AND `status` \u003d 1"; $ res \u003d mysqlQuery ($ sql); // Якщо логін совподает, перевіряємо пароль if (mysql_num_rows ($ res)\u003e 0) (// Отримуємо дані з таблиці $ row \u003d mysql_fetch_assoc ( $ res); if (md5 (md5 ($ _ POST [ "pass"]). $ row [ "salt"]) \u003d\u003d $ row [ "pass"]) ($ _SESSION [ "user"] \u003d true; // скидаємо параметри header ( "Location:". BEZ_HOST. "less / reg /? mode \u003d auth"); exit;) else echo showErrorMessage ( "Неправильний пароль!");) else echo showErrorMessage ( "Логін ". $ _POST [" email "]." не знайден! ");))?\u003e

    Для тих у кого остання версія PHP викладаю даний скрипт з використанням PDO тому розширення MySQL застаріло і було видалено з нової версії PHP. Завантажити реєстрація і авторизація php mysql pdo

    Архів оновлено 24.02.2015г.

    Увага: Якщо ви використовуєте цей скрипт на локальному сервері типу DENWER, XAMPP, То не варто чекати листів на свою поштову скриньку. Листи лежать в заглушці sendmail. В Denwer ви їх можете знайти по шляху Z: \\ tmp \\! Sendmail \\ відкрити ці файли ви зможете в будь-якому поштовому клієнті.

    Будемо вчитися робити просту аутентифікацію користувачів на сайті. На сайті можуть бути сторінки тільки для авторизованих користувачів і вони будуть повноцінно функціонувати, якщо додати до них наш блок аутентифікації. Щоб його створити, потрібна база даних MySQL. Вона може мати 5 колонок (мінімум), а може і більше, якщо ви хочете додати інформацію про користувачів. Назвемо базу даних "Userauth".

    Створимо в ній такі поля: ID для підрахунку числа користувачів, UID для унікального ідентифікаційного номера користувача, Username для імені користувача, Email для адреси його електронної пошти і Password для пароля. Ви можете використовувати для авторизації користувача і вже наявну у Вас базу даних, тільки, як і у випадку з новою базою даних, створіть в ній наступну таблицю.

    код 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;

    Тепер створимо файл "sql.php". Він відповідає за підключення до бази даних. Даний код, по-перше, створює змінні для сервера і користувача, коли він підключається до сервера. По-друге, він вибере базу даних, в даному випадку "USERAUTH". Цей файл потрібно підключити в "log.php" і "reg.php" для доступу до бази даних.

    код PHP

    // Ваше ім'я користувача MySQL $ Pass \u003d "redere"; // пароль $ conn \u003d mysql_connect ($ server, $ user, $ pass); // з'єднання з сервером $ Db \u003d mysql_select_db ( "userauth", $ conn); // вибір бази даних if (! $ db) ( // якщо не може вибрати базу даних echo "Вибачте, помилка: (/\u003e"; // Показує повідомлення про помилку exit (); // Дозволяє працювати іншим скриптам PHP } ?>

    Далі від мене вимагається залогуватись, нехай вона називається "login.php". По-перше, вона перевіряє введені дані на наявність помилок. Сторінка має поля для імені користувача, пароля, кнопку відправки і посилання для реєстрації. Коли користувач натисне кнопку «Вхід», форма буде оброблена кодом з файлу "log.php", а потім відбудеться вхід в систему.

    код PHP

    0) { // якщо є помилки сесії $ Err \u003d "

    "; // Start a table foreach ($ _SESSION [" ERRMSG "] as $ msg) ( // розпізнавання кожної помилки $ Err. \u003d " "; // запис її в змінну ) $ Err. \u003d "
    ". $ Msg."
    "; // закриття таблиці unset ($ _SESSION [ "ERRMSG"]); // видалення сесії } ?> форма входу
    Ім'я користувача
    пароль
    Реєстрація

    Потім пишемо скрипт для входу в систему. Назвемо його "log.php". Він має функцію для очищення вхідних даних від SQL-ін'єкцій, які можуть зіпсувати ваш скрипт. По-друге, він отримує дані форми і перевіряє їх на правильність. Якщо вхідні дані правильні, скрипт відправляє користувача на сторінку авторизованих користувачів, якщо немає - встановлює помилки і відправляє користувача на сторінку входу.

    код PHP

    // початок сесії для запису function Fix ($ str) (// очищення полів $ str \u003d trim ($ str); if (get_magic_quotes_gpc ()) ($ str \u003d stripslashes ($ str);) // масив для збереження помилок $ Errflag \u003d false; // прапор помилки $ username \u003d Fix ($ _ POST [ "username"]); //Ім'я користувача $ Password \u003d Fix ($ _ POST [ "password"]); // пароль) // перевірка пароля if ($ password \u003d\u003d "") ($ errmsg \u003d "Password missing"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки) // якщо прапор помилки піднято, направляє назад до форми реєстрації // записує помилки session_write_close (); // закриття сесії // перенаправлення exit (); ) // запит до бази даних $ Qry \u003d "SELECT * FROM` users` WHERE `Username` \u003d" $ username "AND` Password` \u003d "". Md5 ($ password). "" "; $ Result \u003d mysql_query ($ qry); // перевірка, чи був запит успішним (чи є дані по ньому) if (mysql_num_rows ($ result) \u003d\u003d 1) (while ($ row \u003d mysql_fetch_assoc ($ result)) ($ _SESSION [ "UID"] \u003d $ row [ "UID"]; // отримання UID з бази даних і приміщення його в сесію $ _SESSION [ "USERNAME"] \u003d $ username; // встановлює, чи збігається ім'я користувача з сесійним session_write_close (); // закриття сесії header ( "location: member.php"); // перенаправлення )) Else ($ _SESSION [ "ERRMSG"] \u003d "Invalid username or password"; // помилка session_write_close (); // закриття сесії header ( "location: login.php"); // перенаправлення exit (); )?\u003e

    Зробимо сторінку реєстрації, назвемо її "register.php". Вона схожа на сторінку входу, тільки має на кілька полів більше, а замість посилання на реєстрацію - посилання на login.php на випадок, якщо у користувача вже є аккаунт.

    код PHP

    0) { // якщо є помилки сесії $ Err \u003d "

    "; // початок таблиці foreach ($ _SESSION [" ERRMSG "] as $ msg) ( // встановлює кожну помилку $ Err. \u003d " "; // записує їх в змінну ) $ Err. \u003d "
    ". $ Msg."
    "; // кінець таблиці unset ($ _SESSION [" ERRMSG "]); // знищує сесію } ?> Форма реєстрації
    Ім'я користувача
    E-mail
    пароль
    Повтор пароля
    У мене є аккаунт

    Тепер зробимо скрипт реєстрації в файлі "reg.php". У нього буде включений "sql.php" для підключення до до бази даних. Використовується і та ж функція, що і в скрипті входу для очищення поля введення. Встановлюються змінні для можливих помилок. Далі - функція для створення унікального ідентифікатора, який які ніколи раніше не надавався. Потім беруться дані з форми реєстрації та перевіряються. Відбувається перевірка, що адреса електронної пошти вказано в потрібному форматі, а також, чи правильно повторно зазначений пароль. Потім скрипт перевіряє, чи немає в базі даних користувача з таким же ім'ям, і, якщо є, повідомляє про помилку. І, нарешті, код додає користувача в базу даних.

    код PHP

    // початок сесії для запису function Fix ($ str) (// очищення полів $ str \u003d @trim ($ str); if (get_magic_quotes_gpc ()) ($ str \u003d stripslashes ($ str);) return mysql_real_escape_string($ Str); ) $ Errmsg \u003d array (); // масив для зберігання помилок $ Errflag \u003d false; // прапор помилки $ UID \u003d "+12323543534523453451465685454"; // унікальний ID $ username \u003d Fix ($ _ POST [ "username"]); //Ім'я користувача $ Email \u003d $ _POST [ "email"]; // Email $ password \u003d Fix ($ _ POST [ "password"]); // пароль $ rpassword \u003d Fix ($ _ POST [ "rpassword"]); // повтор пароля // перевірка імені користувача if ($ username \u003d\u003d "") ($ errmsg \u003d "Username missing"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки ) // перевірка Email if (! Eregi ( "^ [_ a-z0-9 -] + (\\. [_ A-z0-9 -] +) * @ + (\\. +) * (\\. (2,3 )) $ ", $ email)) (// повинен відповідати формату: [Email protected] $ Errmsg \u003d "Invalid Email"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки } // перевірка пароля if ($ password \u003d\u003d "") ($ errmsg \u003d "Password missing"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки } // перевірка повтору пароля if ($ rpassword \u003d\u003d "") ($ errmsg \u003d "Repeated password missing"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки } // перевірка валідності пароля if (strcmp ($ password, $ rpassword)! \u003d 0) ($ errmsg \u003d "Passwords do not match"; // помилка $ errflag \u003d true; // піднімає прапор в разі помилки } // перевірка, вільно чи ім'я користувача if ($ username! \u003d "") ($ qry \u003d "SELECT * FROM` users` WHERE `Username` \u003d" $ username ""; // запит до MySQL $ result \u003d mysql_query ($ qry); if ($ result) (if (mysql_num_rows ($ result)\u003e 0) ( // якщо ім'я вже використовується $ Errmsg \u003d "Username already in use"; //повідомлення про помилку $ Errflag \u003d true; // піднімає прапор в разі помилки ) Mysql_free_result ($ result); )) // якщо дані не пройшли валідацію, направляє назад до форми реєстрації if ($ errflag) ($ _SESSION [ "ERRMSG"] \u003d $ errmsg; //повідомлення про помилку session_write_close (); // закриття сесії header ( "location: register.php"); // перенаправлення exit (); ) // додавання даних в базу $ Qry \u003d "INSERT INTO` userauth`.`users` ( \u200b\u200b`UID`,` Username`, `Email`,` Password`) VALUES ( "$ UID", "$ username", "$ email", "". md5 ($ password). "") "; $ Result \u003d mysql_query ($ qry); // перевірка, чи був успішним запит на додавання if ($ result) (echo "Дякуємо Вам за реєстрацію,". $ username. ". Будь ласка, заходьте сюди"; Exit ();) else (die (" Помилка, зверніться пізніше ");)?\u003e

    Ще потрібно зробити скрипт для виходу користувача з системи. Він припиняє сесію для користувача з даними унікальним ідентифікатором і ім'ям, а потім перенаправляє користувача на сторінку входу в систему.

    код PHP

    І, нарешті, скрипт "auth.php" можна використовувати, щоб зробити сторінки доступними тільки для авторизованих користувачів. Він перевіряє дані входу і, якщо вони вірні, дозволяє користувачеві переглядати сторінки, а якщо немає, просить авторизуватися. Крім того, якщо хтось спробує зламати сайт створивши одну з сесій, вона буде перервана, як в загальному випадку.

    код PHP

    Одна з умов в коді вище є предметом питання в.

    Наступний код потрібно вставити на сторінку для авторизованих користувачів, вона називається, наприклад, "member.php", а у Вас може називатися як завгодно.

    код PHP

    Вам дозволений доступ до цієї сторінки. вийти ( )

    Аутентифікація користувачів готова!

    THE BELL

    Є ті, хто прочитали цю новину раніше вас.
    Підпишіться, щоб отримувати статті свіжими.
    Email
    ім'я
    Прізвище
    Як ви хочете читати The Bell
    без спаму