Итак, как я и обещал, сегодня я расскажу как сделать свою авторизацию используя session, php и mysql. Для начала определимся что такое сессия и чем она отличается от cookie.
Session – это механизм, позволяющий однозначно идентифицировать браузер и создающий для этого браузера файл на сервере, в котором хранятся переменные сеанса.
Cookies — это механизм хранения данных браузером удаленного компьютера для идентификации возвращающихся посетителей и хранения параметров веб-страниц.
Т.е. главное различие это место хранения данных, у сессий на стороне сервера, у куков на стороне клиента, это различие критично. Если украсть у пользователя cookie довольно просто то с сессиями не все так просто. Ну а теперь перейдем к практической части а именно к написанию своей авторизации.
Для начала определим имена файлов:
- config.php — хранит данные для подключения к Базе Данных ( далее БД )
- functions.php — содержит в себе все функции для работы авторизации
- join.php — простейший пример регистрации пользователя в системе
- login.php — служит для входа в систему
- logout.php — служит для выхода из системы
- members.php — служит для проверки авторизации ( простейший пример «закрытой» части сайта
Для начала создадим БД и таблицу где будут храниться данные пользователей.
SQL дамп таблицы пользователей
CREATE TABLE users (
id INT(5) NOT NULL AUTO_INCREMENT,
login VARCHAR(15) DEFAULT '0' ,
password VARCHAR(15) DEFAULT '0' ,
PRIMARY KEY (id)
);
config.php
Что содержит данный файл я уже говорил, поэтому просто приведу его код.
<?php
# Запуск сессии
session_start();
# Служит для отладки, показывает все ошибки, предупреждения и т.д.
error_reporting(E_ALL);
# Подключение файлов с функциями
include_once("functions.php");
# В этом массиве далее мы будем хранить сообщения системы, т.е. ошибки.
$messages=array();
# Данные для подключения к БД
$dbhost="localhost";
$dbuser="database_user";
$dbpass="user_password";
$dbname="datebase";
# Вызываем функцию подключения к БД
connectToDB();
?>
functions.php
Самый большой файл из всех в данной статье, содержит все функции. Приведу исходный код а потом прокомментирую каждую функцию.
<?php
function connectToDB() {
global $link, $dbhost, $dbuser, $dbpass, $dbname;
($link = mysql_pconnect("$dbhost", "$dbuser", "$dbpass")) || die("Couldn't connect to MySQL");
mysql_select_db("$dbname", $link) || die("Couldn't open db: $dbname. Error if any was: ".mysql_error() );
}
function newUser($login, $password) {
global $link;
$query="INSERT INTO users (login, password) VALUES('$login', '$password')";
$result=mysql_query($query, $link) or die("Died inserting login info into db. Error returned if any: ".mysql_error());
return true;
}
function displayErrors($messages) {
print("<b>Возникли следующие ошибки:</b>\n<ul>\n");
foreach($messages as $msg){
print("<li>$msg</li>\n");
}
print("</ul>\n");
}
function checkLoggedIn($status){
switch($status){
case "yes":
if(!isset($_SESSION["loggedIn"])){
header("Location: login.php");
exit;
}
break;
case "no":
if(isset($_SESSION["loggedIn"]) && $_SESSION["loggedIn"] === true ){
header("Location: members.php");
}
break;
}
return true;
}
function checkPass($login, $password) {
global $link;
$query="SELECT login, password FROM users WHERE login='$login' and password='$password'";
$result=mysql_query($query, $link)
or die("checkPass fatal error: ".mysql_error());
if(mysql_num_rows($result)==1) {
$row=mysql_fetch_array($result);
return $row;
}
return false;
}
function cleanMemberSession($login, $password) {
$_SESSION["login"]=$login;
$_SESSION["password"]=$password;
$_SESSION["loggedIn"]=true;
}
function flushMemberSession() {
unset($_SESSION["login"]);
unset($_SESSION["password"]);
unset($_SESSION["loggedIn"]);
session_destroy();
return true;
}
function field_validator($field_descr, $field_data, $field_type, $min_length="", $max_length="", $field_required=1) {
global $messages;
if(!$field_data && !$field_required){ return; }
$field_ok=false;
$email_regexp="^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|";
$email_regexp.="(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
$data_types=array(
"email"=>$email_regexp,
"digit"=>"^[0-9]$",
"number"=>"^[0-9]+$",
"alpha"=>"^[a-zA-Z]+$",
"alpha_space"=>"^[a-zA-Z ]+$",
"alphanumeric"=>"^[a-zA-Z0-9]+$",
"alphanumeric_space"=>"^[a-zA-Z0-9 ]+$",
"string"=>""
);
if ($field_required && empty($field_data)) {
$messages[] = "Поле $field_descr является обезательным";
return;
}
if ($field_type == "string") {
$field_ok = true;
} else {
$field_ok = ereg($data_types[$field_type], $field_data);
}
if (!$field_ok) {
$messages[] = "Пожалуйста введите нормальный $field_descr.";
return;
}
if ($field_ok && ($min_length > 0)) {
if (strlen($field_data) < $min_length) {
$messages[] = "$field_descr должен быть не короче $min_length символов.";
return;
}
}
if ($field_ok && ($max_length > 0)) {
if (strlen($field_data) > $max_length) {
$messages[] = "$field_descr не должен быть длиннее $max_length символов.";
return;
}
}
}
?>
А теперь по порядку
- function connectToDB() — служит для подключения к базе данных
- function newUser($login, $password) — служит для создания нового пользователя в системе
- function displayErrors($messages) — выводит массив ошибок
- function checkLoggedIn($status) — проверяет авторизацию пользователя.
- function checkPass($login, $password) — проверяет пользователя по БД во время авторизации
- function cleanMemberSession($login, $password) — авторизует пользователя
- function flushMemberSession() — выход, или если вам будет удобнее logout
- function field_validator($field_descr, $field_data, $field_type, $min_length=»», $max_length=»», $field_required=1) — Валидатор данных, проверяет соответствие полей требованиям системы
Работу каждой функции я описывать не буду, т.к. они довольно простые, в данный момент нас интересует только логика. Если будут вопросы — спрашивайте.
join.php
Итак исходник:
<?php
include_once("config.php");
checkLoggedIn("no");
$title="страница регистрации";
if(isset($_POST["submit"])){
field_validator("login name", $_POST["login"], "alphanumeric", 4, 15);
field_validator("password", $_POST["password"], "string", 4, 15);
field_validator("confirmation password", $_POST["password2"], "string", 4, 15);
if(strcmp($_POST["password"], $_POST["password2"])) {
$messages[]="Ваши пароли не совпадают";
}
$query="SELECT login FROM users WHERE login='".$_POST["login"]."'";
$result=mysql_query($query, $link) or die("MySQL query $query failed. Error if any: ".mysql_error());
if( ($row=mysql_fetch_array($result)) ){
$messages[]="Логин \"".$_POST["login"]."\" уже занят, попробуйте другой.";
}
if(empty($messages)) {
newUser($_POST["login"], $_POST["password"]);
cleanMemberSession($_POST["login"], $_POST["password"]);
header("Location: members.php");
}
}
?>
<html>
<head>
<title><?php print $title; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=uft-8">
</head>
<body>
<h1><?php print $title; ?></h1>
<?php
if(!empty($messages)){
displayErrors($messages);
}
?>
<form action="<?php print $_SERVER["PHP_SELF"]; ?>" method="POST">
<table>
<tr><td>Логин:</td><td><input type="text" name="login"
value="<?php print isset($_POST["login"]) ? $_POST["login"] : "" ; ?>"
maxlength="15"></td></tr>
<tr><td>Пароль:</td><td><input type="password" name="password" value="" maxlength="15"></td></tr>
<tr><td>Повторить пароль:</td><td><input type="password" name="password2" value="" maxlength="15"></td></tr>
<tr><td> </td><td><input name="submit" type="submit" value="Submit"></td></tr>
</table>
</form>
</body>
</html>
Если кратко описать работу скрипта получится что то вроде:
1. Если уже авторизованы пересылаем на members.php ( строка 4 )
2. Если существует $_POST[‘submit’] ( если отправили данные с формы ) проверяем поля валидатором, проверяем наличие такого пользователя, если никаких ошибок нет, добавляем нового пользователя, ставим сессию и пускаем на members.php
3. Если есть ошибки — выводим
4. Выводим форму
login.php
Код:
<?php
include_once("config.php");
checkLoggedIn("no");
$title="Страница авторизации";
if(isset($_POST["submit"])) {
field_validator("login name", $_POST["login"], "alphanumeric", 4, 15);
field_validator("password", $_POST["password"], "string", 4, 15);
if($messages){
doIndex();
exit;
}
if( !($row = checkPass($_POST["login"], $_POST["password"])) ) {
$messages[]="Incorrect login/password, try again";
}
if($messages){
doIndex();
exit;
}
cleanMemberSession($row["login"], $row["password"]);
header("Location: members.php");
} else {
doIndex();
}
function doIndex() {
global $messages;
global $title;
?>
<html>
<head>
<title><?php print $title; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<h1><?php print $title; ?></h1>
<?php
if($messages) { displayErrors($messages); }
?>
<form action="<?php print $_SERVER["PHP_SELF"]; ?>" method="POST">
<table>
<tr><td>Логин:</td><td><input type="text" name="login"
value="<?php print isset($_POST["login"]) ? $_POST["login"] : "" ; ?>"
maxlength="15"></td></tr>
<tr><td>Пароль:</td><td><input type="password" name="password" value="" maxlength="15"></td></tr>
<tr><td> </td><td><input name="submit" type="submit" value="Submit"></td></tr>
</table>
</form>
</body>
</html>
<?php
}
?>
Во первых тут стоит указать что вывод html и ошибок происходит в функции doIndex() которая вызывается в некоторых случаях, это не очень удобно поэтому кто хочет переписать — милости прошу, лично я сделал это для примера, к каждому проекту я пишу собственную авторизацию и стараюсь не повторяться. Поэтому здесь только пример.
А теперь по порядку.
1. подключаем конфиг
2. если уже авторизованы пересылаем на страницу members.php ( функция checkLoggedIn с параметром no )
3. Если отправлена форма, проверяем поля валидатором, если есть ошибки вызываем функцию doIndex(), если пароли не совпадают ставим ошибку, если есть ошибки вызываем функцию doIndex(), если все в порядке ставим сессию и отправляем на members.php, иначе опять вызываем функцию doIndex()
4. Функция doIndex() выводит html код, ошибки и форму для авторизации.
logout.php
<?php
include_once("config.php");
checkLoggedIn("yes");
flushMemberSession();
header("Location: login.php");
?>
Тут все просто:
1. Подключаем конфиг
2. Проверяем авторизован ли пользователь
3. Уничтожаем сессию
4. Отправляем пользователя на страницу авторизации
members.php
<?php
include_once("config.php");
checkLoggedIn("yes");
print("<b>".$_SESSION["login"]."</b>! Добро пожаловать<br>\n");
print("Ваш пароль: <b>".$_SESSION["password"]."</b><br>\n");
print("<a href=\"logout.php"."\">Выход</a>");
?>
Тоже все просто, подключаем конфиг, проверяем авторизован ли и выводи данные пользователя.
Ну вот собственно и все, хотя все довольно просто — пожалуй это самая длинная моя статья в блоге на данный момент. Если что то не понятно — спрашивайте! И если вы нашли ошибки или есть замечания, не молчите 🙂
Добавить комментарий