Содержание

Пишем свою авторизацию на PHP и MySQL -Будни программиста

Ну что же, сегодня я вам расскажу о безопасной авторизации на PHP и Cookie. Ну о том что она абсолютна безопасна я не говорю, ибо взломать можно все, но для маленького сайта она вполне подходит. Так же я предвижу комментарии о том что сессии безопаснее. Не спорю куки уступают сессиям в безопасности но для реализации простенькой авторизации вполне подходят. Подробности ниже.

И так, в базе у нас будет 1 база из 4 полей: users_id, users_login, users_password и users_hash. SQL запрос:

1
2
3
4
5
6
7

CREATE TABLE IF NOT EXISTS `users` (
  `users_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `users_login` VARCHAR(30) NOT NULL,
  `users_password` VARCHAR(32) NOT NULL,
  `users_hash` VARCHAR(32) NOT NULL,
  PRIMARY KEY  (`users_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

    Сам скрипт авторизации будет тоже на 4 файлах. А именно:
  • conf.php — Файл конфигурации, в котором так же содержится подключение к бд;
  • register.php — Регистрация нового пользователя;
  • login.php — Авторизация пользователя;
  • check.php — Скрипт проверки авторизации;

Давайте разберем каждый файл.

conf.php

В константах содержится данные SQL подключения, а именно хост, логин, пароль и имя вашей базы. Тут же мы подключаемся к базе, устанавливаем кодировку в которой будут передаваться данные в бд и выбираем бд с которой будем работать. Так же тут содержится массив ошибок которые могут возникнуть при авторизации.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

<?php
# настройки
define (‘DB_HOST’, ‘localhost’);
define (‘DB_LOGIN’, ‘example_user’);
define (‘DB_PASSWORD’, ‘example_password’);
define (‘DB_NAME’, ‘example_base’);
mysql_connect(DB_HOST, DB_LOGIN, DB_PASSWORD) or die («MySQL Error: » . mysql_error());
mysql_query(«set names utf8») or die («<br>Invalid query: » . mysql_error());
mysql_select_db(DB_NAME) or die («<br>Invalid query: » . mysql_error());

# массив ошибок
$error[0] = ‘Я вас не знаю’;
$error[1] = ‘Включи куки’;
$error[2] = ‘Тебе сюда нельзя’;
?>

register.php

Файл регистрации, тут содержится простейшая форма и ее обработчик. Исходный код прокомментирован, но общий процесс я коротко опишу. Вначале проверяем наш логин, он может содержать только английские буквы и цифры. Далее мы проверяем длину логина, от 3 до 30 символов. Проверяем свободен ли логин. При успешных проверках добавляем нового пользователя в базу. Из введенного пароля мы вырезаем пробелы на случай если пользователь хранит свои пароли в каком ни будь текстовом файле (в windows текстовые редакторы любят «хватать» пробелы в начале или конце выделяемого текста). Шифруем пароль в двойном MD5 и добавляем в базу данные о новом пользователе. Перебрасываем пользователя на login.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

<?php
# Подключаем конфиг
include ‘conf.php’;

if(isset($_POST[‘submit’]))
{

    $err = array();

    # проверям логин
   if(!preg_match(«/^[a-zA-Z0-9]+$/»,$_POST[‘login’]))
    {
        $err[] = «Логин может состоять только из букв английского алфавита и цифр»;
    }
     
    if(strlen($_POST[‘login’]) < 3 or strlen($_POST[‘login’]) > 30)
    {
        $err[] = «Логин должен быть не меньше 3-х символов и не больше 30»;
    }
     
    # проверяем, не сущестует ли пользователя с таким именем
  $query = mysql_query(«SELECT COUNT(users_id) FROM users WHERE users_login='».mysql_real_escape_string($_POST[‘login’]).»‘»)or die («<br>Invalid query: » . mysql_error());
    if(mysql_result($query, 0) > 0)
    {
        $err[] = «Пользователь с таким логином уже существует в базе данных»;
    }
 
     
    # Если нет ошибок, то добавляем в БД нового пользователя
   if(count($err) == 0)
    {
         
        $login = $_POST[‘login’];
         
        # Убераем лишние пробелы и делаем двойное шифрование
       $password = md5(md5(trim($_POST[‘password’])));
         
        mysql_query(«INSERT INTO users SET users_login='».$login.»‘, users_password='».$password.»‘»);
        header(«Location: login.php»); exit();
    }
}
?>

  <form method=»POST» action=»»>
  Логин <input type=»text» name=»login» /><br />
  Пароль <input type=»password» name=»password» /><br />
  <input name=»submit» type=»submit» value=»Зарегистрироваться»>
  </form>
  <?php
    if (isset($err)) {
      print «<b>При регистрации произошли следующие ошибки:</b><br>»;
      foreach($err AS $error)
      {
        print $error.»<br>»;
      }  
    }
  ?>

login.php

Опять кратко расскажу о действиях совершаемых в данном скрипте. В самом начале у нас висит функция для генерации случайной строки, она служит для хеша пользователя (чуть позже более подробно). Далее мы проверяем наличие куков с ошибками (они ставятся в check.php). Подключаем файл конфигурации и проверяем пользователя. Вытаскиваем из бд логин и пароль, сравниваем с введенными и генерируем хеш. Записываем в бд новый хеш пользователя и ставим куки. В куках находится id и хеш пользователя. Пересылаем пользователя на check.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

<?php
  # Функция для генерации случайной строки
  function generateCode($length=6) {
    $chars = «abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRQSTUVWXYZ0123456789»;
    $code = «»;
    $clen = strlen($chars) — 1;  
    while (strlen($code) < $length) {
        $code .= $chars[mt_rand(0,$clen)];  
    }
    return $code;
  }
 
  # Если есть куки с ошибкой то выводим их в переменную и удаляем куки
  if (isset($_COOKIE[‘errors’])){
      $errors = $_COOKIE[‘errors’];
      setcookie(‘errors’, », time() — 60*24*30*12, ‘/’);
  }

  # Подключаем конфиг
  include ‘conf.php’;

  if(isset($_POST[‘submit’]))
  {
   
    # Вытаскиваем из БД запись, у которой логин равняеться введенному
    $data = mysql_fetch_assoc(mysql_query(«SELECT users_id, users_password FROM `users` WHERE `users_login`='».mysql_real_escape_string($_POST[‘login’]).»‘ LIMIT 1″));
     
    # Соавниваем пароли
    if($data[‘users_password’] === md5(md5($_POST[‘password’])))
    {
      # Генерируем случайное число и шифруем его
      $hash = md5(generateCode(10));
           
      # Записываем в БД новый хеш авторизации и IP
      mysql_query(«UPDATE users SET users_hash='».$hash.»‘ WHERE users_id='».$data[‘users_id’].»‘») or die(«MySQL Error: » . mysql_error());
       
      # Ставим куки
      setcookie(«id», $data[‘users_id’], time()+60*60*24*30);
      setcookie(«hash», $hash, time()+60*60*24*30);
       
      # Переадресовываем браузер на страницу проверки нашего скрипта
      header(«Location: check.php»); exit();
    }
    else
    {
      print «Вы ввели неправильный логин/пароль<br>»;

    }
  }
?>
  <form method=»POST»>
  Логин <input name=»login» type=»text»><br>
  Пароль <input name=»password» type=»password»><br>
  <input name=»submit» type=»submit» value=»Войти»>
  </form>
  <?php
  # Проверяем наличие в куках номера ошибки
  if (isset($errors)) {print ‘<h5>’.$error[$errors].'</h5>’;}

  ?>

check.php

И последний файл, который содержит проверку авторизации пользователя. В начале подключаем конфиг и если существуют куки начинаем проверку, если их нет, то ставим куки с номером ошибки и отсылаем на login.php. И так проверка. Вытаскиваем из бд id и хеш. Если они не проходят проверку на соответствие с теми куками которые стоят у посетителя, то удаляем существующие куки посетителя и ставим куки с номером ошибки, пересылаем на login.php. Если же все нормально то пользователь увидит страницу.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

<?php
# подключаем конфиг
include ‘conf.php’;  

# проверка авторизации
if (isset($_COOKIE[‘id’]) and isset($_COOKIE[‘hash’]))
{    
    $userdata = mysql_fetch_assoc(mysql_query(«SELECT * FROM users WHERE users_id = ‘».intval($_COOKIE[‘id’]).»‘ LIMIT 1″));

    if(($userdata[‘users_hash’] !== $_COOKIE[‘hash’]) or ($userdata[‘users_id’] !== $_COOKIE[‘id’]))
    {
        setcookie(‘id’, », time() — 60*24*30*12, ‘/’);

        setcookie(‘hash’, », time() — 60*24*30*12, ‘/’);
    setcookie(‘errors’, ‘1’, time() + 60*24*30*12, ‘/’);
    header(‘Location: login.php’); exit();
    }
}
else
{
  setcookie(‘errors’, ‘2’, time() + 60*24*30*12, ‘/’);
  header(‘Location: login.php’); exit();
}
?>
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml» xml:lang=»en»>
<head>
  <meta http-equiv=»Content-Type» content=»text/html;charset=UTF-8″ />
  <title></title>
</head>
<body>
  hello!
</body>
</html>

Выход

Выход можно осуществить любым удобным для вас способом просто удалив куки, допустим так:

1
2
3
4
5
6
7
8
9

<form action=»» method=»post»><input type=’submit’ name=’exit’ value=’Выйти’/></form>
<?php
if($_REQUEST[‘exit’])
  {
        setcookie(‘id’, », time() — 60*60*24*30, ‘/’);
        setcookie(‘hash’, », time() — 60*60*24*30, ‘/’);
        header(‘Location: login.php’); exit();
  }
?>

Сразу хочу предупредить о том что ваши файлы должны быть в кодировке UTF8 и БЕЗ BOM! Приятного пользования!

Теги: Cookie, MD5, MySQL, PHP, Авторизация

Как сделать систему авторизации и регистрации на PHP

// Проверяем нажата ли кнопка отправки формы

if (isset($_REQUEST[‘doGo’])) {

    

    // Все последующие проверки, проверяют форму и выводят ошибку

    // Проверка на совпадение паролей

    if ($_REQUEST[‘pass’] !== $_REQUEST[‘pass_rep’]) {

        $error = ‘Пароль не совпадает’;

    }

    

    // Проверка есть ли вообще повторный пароль

    if (!$_REQUEST[‘pass_rep’]) {

        $error = ‘Введите повторный пароль’;

    }

    

    // Проверка есть ли пароль

    if (!$_REQUEST[‘pass’]) {

        $error = ‘Введите пароль’;

    }

    // Проверка есть ли email

    if (!$_REQUEST[’email’]) {

        $error = ‘Введите email’;

    }

    // Проверка есть ли логин

    if (!$_REQUEST[‘login’]) {

        $error = ‘Введите login’;

    }

    // Если ошибок нет, то происходит регистрация

    if (!$error) {

        $login = $_REQUEST[‘login’];

        $email = $_REQUEST[’email’];

        // Пароль хешируется

        $pass = password_hash($_REQUEST[‘pass’], PASSWORD_DEFAULT);

        // Если день рождения не был указан, то будет самый последний год из доступных

        $DOB = $_REQUEST[‘year_of_birth’];

        

        // Добавление пользователя

        mysqli_query($db, «INSERT INTO `users` (`login`, `email`, `password`, `DOB`) VALUES (‘» . $login . «‘,'» . $email . «‘,'» . $pass . «‘, ‘» . $DOB . «‘)»);

        

        // Подтверждение что всё хорошо

        echo ‘Регистрация прошла успешна’;

    } else {

        // Если ошибка есть, то выводить её

        echo $error;

    }

}

?>

<!DOCTYPE html>

<html lang=»ru»>

<head>

    <meta charset=»UTF-8″>

    <meta name=»viewport» content=»width=device-width, initial-scale=1.0″>

    <meta http-equiv=»X-UA-Compatible» content=»ie=edge»>

    <title>Зарегистрироваться</title>

</head>

<body>

    <form action=»<?= $_SERVER[‘SCRIPT_NAME’] ?>»>

        <p>Логин: <input type=»text» name=»login»> <samp>*</samp></p>

        <p>EMail: <input type=»email» name=»email»><samp>*</samp></p>

        <p>Пароль: <input type=»password» name=»pass»><samp>*</samp></p>

        <p>Повторите пароль: <input type=»password» name=»pass_rep»><samp>*</samp></p>

        <?php $year = date(‘Y’); ?>

        Год рождения:

        <select name=»year_of_birth»>

        <option value=»»>—-</option>

            <?php for ($i = $year — 14; $i > $year — 14 — 100; $i—) { ?>

                <option value=»<?= $i ?>»><?= $i ?></option>

            <?php } ?>

        </select>

        <p><input type=»submit» value=»Зарегистрироваться» name=»doGo»></p>

    </form>

</body>

</html>

Пишем авторизацию пользователя на PHP — Блог веб-разработчиков

Совсем недавно я рассказывал, как при помощи PHP написать систему регистрации для своего сайта. Такой же принцип мы использовали и в своём проекте, созданию которого посвящён раздел «Сайт с нуля» на этом блоге (сам проект я покажу вам гораздо позже). Сегодня же я опишу, как написать авторизацию на сайте, используя данные, полученные от пользователя при регистрации. То есть, будет использоваться таблица MySQL, структура которой была описана в статье про регистрацию. Поэтому я настоятельно рекомендую прежде прочитать ту статью, ибо данная статья является её непосредственным продолжением. Авторизация будет работать с использованием сессий и cookie. Также в статье будет рассмотрено несколько приятных дополнений, таких, как «разлогинивание» (выход) и время последней активности пользователя. Итак, приступим…

Для начала необходимо сверстать главную страницу сайта и поместить её в корне сайта в папку template. Для данного урока нам достаточно, чтобы в этом файле была форма ввода логина и пароля, а также кнопка «Вход». Далее приведён код этой формы:

1
2
3
4
5
<form action="/" method="post">
 Логин: <input type="text" name="login" />

 Пароль: <input type="password" name="password" />
 <input type="submit" value="Войти" name="log_in" />

 </form>

Файл назовём index.html.

Метод передачи post необходим. Ведь мы не хотим, чтобы при авторизации логин и пароль светились в адресной строке.

Как только форма готова, создадим самый важный файл будущего сайта — главный контроллер, т. е. файл, лежащий в корне сайта — index.php. Именно он и будет запускаться при входе на сайт. На момент написания статьи на нашем проекте код этого файла занимает 92 строки, нам же понадобится пока лишь около 25 строк. Вот его код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?
include ('lib/connect.php'); //подключаемся к БД
include ('lib/module_global.php'); //подключаем файл с глобальными функциями

 
if($_GET['action'] == "out") out(); //если передана переменная action, «разавторизируем» пользователя
 
if (login()) //вызываем функцию login, определяющую, авторизирован юзер или нет

{
	$UID = $_SESSION['id']; //если юзер авторизирован, присвоим переменной $UID его id
	$admin = is_admin($UID); //определяем, админ ли юзер

}
else //если пользователь не авторизирован, то проверим, была ли нажата кнопка входа на сайт
{
	if(isset($_POST['log_in'])) 
	{
		$error = enter(); //функция входа на сайт

		if (count($error) == 0) //если нет ошибок, авторизируем юзера
		{
			$UID = $_SESSION['id'];

			$admin = is_admin($UID);
		}
	}
}
include ('tpl/index.html'); //подключаем файл с формой

?>

Теперь более подробно разберёмся, как всё это работает.

В первых трёх строках мы просто подключаем файлы с функциями, которые будем использовать далее в коде. О них чуть позже. Далее проверим, был ли передан get-параметр action=out. Если он был передан, значит пользователь нажал на ссылку выхода с сайта. Вот, кстати, код этой ссылки. Добавьте его в файл с кодом формы для входа.

<a href="/?action=out">Выход</a>

Саму функцию, как и все остальные, рассмотрим позже. Сперва логика…

Далее идёт условие, проверяющее авторизирован ли ты (if (login())). Функция возвращает true в случае, если пользователь вошёл на сайт и false в противном случае. Если вернулось true, записываем в переменную $UID id юзера, а в переменную $admin — результат работы функции is_admin($UID). Данная функция определяет, является ли пользователь администратором и возвращает true, если юзер — админ и false в противном случае. В дальнейшем две эти переменные будут необходимы для вывода определённых элементов на странице. Так, следующим условием можно вывести форму авторизации:

1
2
3
4
5
6
7
8
9
10
<?
If($UID) //если переменной нет, выводим форму
{?>
<form action="/" method="post">

Логин: <input type="text" name="login" />
Пароль: <input type="password" name="password" />

<input type="submit" value="Войти" name="log_in" />
</form>
<?}
?>

Аналогично и с переменной $admin. Кстати, последний код можно включить в файл с формой.
Если же функция login() вернёт false, т. е. пользователь не вошёл на сайт, проверим, нажал ли он на кнопку входа на сайт в форме авторизации:

if(isset($_POST['log_in']))

Если да, запускаем функцию enter(), авторизирующую пользователя. Если ошибок не произойдёт и юзер успешно вошёл, создадим те же 2 переменные: $UID и $admin. В противном случае никакие переменные не создаются – пользователь является гостем. Алгоритм работы представлен на следующей схеме:

Теперь разберёмся со всеми функциями, вызываемыми в данном коде. В первую очередь опишу функцию входа на сайт:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

function enter ()
 { 
$error = array(); //массив для ошибок 	
if ($_POST['login'] != "" && $_POST['password'] != "") //если поля заполнены 	

{ 		
	$login = $_POST['login']; 
	$password = $_POST['password'];

	$rez = mysql_query("SELECT * FROM users WHERE login=$login"); //запрашиваем строку из БД с логином, введённым пользователем 		
	if (mysql_num_rows($rez) == 1) //если нашлась одна строка, значит такой юзер существует в БД 		

	{ 			
		$row = mysql_fetch_assoc($rez); 			
		if (md5(md5($password).$row['salt']) == $row['password']) //сравниваем хэшированный пароль из БД с хэшированными паролем, введённым пользователем и солью (алгоритм хэширования описан в предыдущей статье) 						

		{ 
		//пишем логин и хэшированный пароль в cookie, также создаём переменную сессии
		setcookie ("login", $row['login'], time() + 50000); 						
		setcookie ("password", md5($row['login'].$row['password']), time() + 50000); 					
		$_SESSION['id'] = $row['id'];	//записываем в сессию id пользователя 				

		$id = $_SESSION['id']; 				
		lastAct($id); 				
		return $error; 			
	} 			
	else //если пароли не совпали 			

	{ 				
		$error[] = "Неверный пароль"; 										
		return $error; 			
	} 		
} 		
	else //если такого пользователя не найдено в БД 		

	{ 			
		$error[] = "Неверный логин и пароль"; 			
		return $error; 		
	} 	
} 	
 

	else 	
	{ 		
		$error[] = "Поля не должны быть пустыми!"; 				
		return $error; 	
	} 

}

Первым делом, функция проверяет, заполнил ли пользователь поля для ввода логина и пароля. Если да — продолжаем работу программы, если нет — пишем в массив $error текст ошибки и возвращаем его в основную программу, которая, узнав размерность полученного массива, не авторизирует пользователя.
Если же работа функции enter() продолжится, проверим, существует ли в БД запись с таким ником, какой ввёл юзер. Если такой записи не оказалось, вернём опять же массив с соответствующей ошибкой. Если в БД есть один пользователь с таким ником, сравним введённый пароль с паролем, хранящимся в базе данных и соответствующим нашему нику.

Сравниваем мы пароли не в чистом виде. Ведь в БД они хранятся хэшированными функцией md5(). Поэтому, прежде чем сравнивать их, необходимо тем же алгоритмом хэшировать и введённый пользователем при авторизации пароль. Если хэши совпадут, значит логин и пароль совпали и скрипт авторизирует пользователя. Если совпадения не произошло, вернём ошибку.

Теперь объясню, что же значит «авторизироваться». В данном скрипте данные об авторизации хранятся в сессии и cookie. В сессию записываем id пользователя:

И создаём два cookie: login и password с продолжительностью жизни — 50000 секунд. В первый пишем логин, а во второй — хэш пароля.

В этой строке мы выполняем функцию, отвечающую за установку времени последней активности юзера. Вот код этой функции:

1
2
function lastAct($id)
{ 	$tm = time(); 	mysql_query("UPDATE users SET online='$tm', last_act='$tm' WHERE"); }

Функция перезаписывает поля online и last_act в БД. Кстати, предварительно, необходимо убедиться в существовании этих полей. Оба они имеют тип int.

Алгоритм работы функции enter() приведён на следующей иллюстрации:

Следующая функция отвечает за проверку, авторизирован ли пользователь на сайте или нет — login().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
function login () { 	
ini_set ("session.use_trans_sid", true); 	session_start();  	if (isset($_SESSION['id']))//если сесcия есть 	

{ 		
if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если cookie есть, то просто обновим время их жизни и вернём true 		{ 			
SetCookie("login", "", time() - 1, '/'); 			SetCookie("password","", time() - 1, '/'); 			

setcookie ("login", $_COOKIE['login'], time() + 50000, '/'); 			

setcookie ("password", $_COOKIE['password'], time() + 50000, '/'); 			

$id = $_SESSION['id']; 			
lastAct($id); 			
return true; 		

} 		
else //иначе добавим cookie с логином и паролем, чтобы после перезапуска браузера сессия не слетала  		
{ 			
$rez = mysql_query("SELECT * FROM users WHEREid']}'"); //запрашиваем строку с искомым id 			

if (mysql_num_rows($rez) == 1) //если получена одна строка 			{ 		
$row = mysql_fetch_assoc($rez); //записываем её в ассоциативный массив 				

setcookie ("login", $row['login'], time()+50000, '/'); 				

setcookie ("password", md5($row['login'].$row['password']), time() + 50000, '/'); 

$id = $_SESSION['id'];
lastAct($id); 
return true; 			

} 
else return false; 		
} 	
} 	
else //если сессии нет, то проверим существование cookie. Если они существуют, то проверим их валидность по БД 	
{ 		
if(isset($_COOKIE['login']) && isset($_COOKIE['password'])) //если куки существуют. 		

{ 			
$rez = mysql_query("SELECT * FROM users WHERE login='{$_COOKIE['login']}'"); //запрашиваем строку с искомым логином и паролем 			
@$row = mysql_fetch_assoc($rez); 			

if(@mysql_num_rows($rez) == 1 && md5($row['login'].$row['password']) == $_COOKIE['password']) //если логин и пароль нашлись в БД 			

{ 				
$_SESSION['id'] = $row['id']; //записываем в сесиию id 				
$id = $_SESSION['id']; 				

lastAct($id); 				
return true; 			
} 			
else //если данные из cookie не подошли, то удаляем эти куки, ибо нахуй они такие нам не нужны 			
{ 				
SetCookie("login", "", time() - 360000, '/'); 				

SetCookie("password", "", time() - 360000, '/');	 				
return false; 			

} 		
} 		
else //если куки не существуют 		
{ 			
return false; 		
} 	
} 
}

Почему для авторизации мы будем использовать и COOKIE и сессию? Дело в том, что после закрытия браузера, сессия «умирает» и пользователь автоматически разлогинивается. Cookie же хранятся определённое, задаваемое нами, время. В данном случае это 50000 секунд.

Итак, разберёмся, как же эта функция работает. Её стоит запускать первой на всех страницах и модулях будущего сайта. Во-первых, она проверяет, авторизирован ли пользователь, что для дальнейшей работы скрипта крайне важно. Во-вторых, она обновляет время последней активности пользователя, а также поможет в будущем ввести систему онлайн-пользователей.

Функция вернёт true, если юзер авторизирован и false в противном случае. Пичём, в процессе её работы, будет обновлено время жизни cookie, а также они будут созданы, если не существуют.

Лучше всего работу функции online описывает эта иллюстрация:

Если есть сессия и cookie, мы обновляем время жизни cookie. Для этого мы их удаляем, устанавливая время смерти на одну секунду раньше текущего момента времени, а затем устанавливаем заново. Также функцией lastAct() обновлем время последней активности. Возвращаем true.

Если же сессия есть, а cookie по какой-то причине не оказалось, то по id пользователя получаем из БД логин и хэш пароля и пишем их в cookie. Возвращаем true.

Если нет сессии, проверим, быть может существуют cookie. Классический пример авторизации после перезапуска браузера — сессия слетела, но cookie-то живы. Тут уже сложнее, мы должны проверить, совпадает ли пара логин-пароль с какой-либо строкой из БД. Ведь юзер мог заменить в настройках для сайта cookie ручками или написать любую чушь. Если такая пара нашлась, создаём переменную сессии и возвращаем true. Если же пара не найдена, посылаем пользователя на йух и возвращаем false.

Последний, самый печальный вариант — когда ни сессии, ни cookie не оказалось… Возвращаем false.

Теперь обратим взор на функцию is_admin($UID). Она определяет, является ли юзер администратором сайта. Возможно, вам это не нужно, тогда можете опустить эту функцию и все её вызовы в контроллере. Но она может быть полезна для вывода какого либо контента на страницу, предназначенного для администраторов, а не для обычных пользователей. Функция простая и основана на ещё одном созданном столбце в БД в таблице users. Столбец называем prava. Тип int. Если юзер является обыкновенным пользователем, то присваиваем значению в этом столбце 0, если же этот юзер — админ, то присваиваем единицу. Следующая функция и определяет, что стоит в столбце prava; если единица, то возвращается true (пользователь – админ), иначе false.

1
2
3
4
5
6
7
8
9
10
function is_admin($id) { 	
@$rez = mysql_query("SELECT prava FROM users WHERE"); 	

if (mysql_num_rows($rez) == 1) 	
{ 		
$prava = mysql_result($rez, 0); 		

if ($prava == 1) return true; 		
else return false; 

} 	
else return false;	 
}

Ну и последняя, на самом деле очень лёгкая, функция — out(). Принцип её работы прост — удалить все «следы» пользователя – сессию и cookie.

1
2
3
4
5
6
7
8
function out () { 	
session_start(); 	
$id = $_SESSION['id'];			 	

mysql_query("UPDATE users SET online=0 WHERE"); //обнуляем поле online, говорящее, что пользователь вышел с сайта (пригодится в будущем) 	
unset($_SESSION['id']); //удаляем переменную сессии 	
SetCookie("login", ""); //удаляем cookie с логином 	

SetCookie("password", ""); //удаляем cookie с паролем  	
header('Location: http://'.$_SERVER['HTTP_HOST'].'/'); //перенаправляем на главную страницу сайта }

Код всех описанных функций помещаем в файл lib/module_global.php, который подключается в самом начале работы контроллера.

Таким образом, мы написали простую, однако достаточно функциональную регистрацию для своего будущего сайта. В придачу ко всему мы заложили некоторый фундамент для ещё не рассмотренных возможностей: администрирование, онлайн-пользователи, время последней активности. Также авторизация не будет слетать после перезапуска браузера, что достигнуто путём использования cookie. Кроме этого мы предусмотрели и выход с сайта.

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

Чтобы не пропустить следующие статьи, подпишитесь на RSS.

Удачи и до следующих статей.

Авторизация на сессиях PHP и MySQL -Будни программиста


Итак, как я и обещал, сегодня я расскажу как сделать свою авторизацию используя session, php и mysql. Для начала определимся что такое сессия и чем она отличается от cookie.
Session – это механизм, позволяющий однозначно идентифицировать браузер и создающий для этого браузера файл на сервере, в котором хранятся переменные сеанса.
Cookies — это механизм хранения данных броузером удаленного компьютера для идентификации возвращающихся посетителей и хранения параметров веб-страниц.
Т.е. главное различие это место хранения данных, у сессий на стороне сервера, у куков на стороне клиента, это различие критично. Если украсть у пользователя cookie довольно просто то с сессиями не все так просто. Ну а теперь перейдем к практической части а именно к написанию своей авторизации.
Для начала определим имена файлов:

  • config.php — хранит данные для подключения к Базе Данных ( далее БД )
  • functions.php — содержит в себе все функции для работы авторизации
  • join.php — простейший пример регистрации пользователя в системе
  • login.php — служит для входа в систему
  • logout.php — служит для выхода из системы
  • members.php — служит для проверки авторизации ( простейший пример «закрытой» части сайта

Для начала создадим БД и таблицу где будут храниться данные пользователей.

SQL дамп таблицы пользователей

1
2
3
4
5
6

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

Что содержит данный файл я уже говорил, поэтому просто приведу его код.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<?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

Самый большой файл из всех в данной статье, содержит все функции. Приведу исходный код а потом прокомментирую каждую функцию.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

<?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

Итак исходник:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

<?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>
<h2><?php print $title; ?></h2>
<?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>&nbsp;</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

Код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

<?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>
<h2><?php print $title; ?></h2>
<?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>&nbsp;</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

1
2
3
4
5
6

<?php
include_once(«config.php»);
checkLoggedIn(«yes»);
flushMemberSession();
header(«Location: login.php»);
?>

Тут все просто:
1. Подключаем конфиг
2. Проверяем авторизован ли пользователь
3. Уничтожаем сессию
4. Отправляем пользователя на страницу авторизации

members.php

1
2
3
4
5
6
7

<?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>»);
?>

Тоже все просто, подключаем конфиг, проверяем авторизован ли и выводи данные пользователя.

Ну вот собственно и все, хотя все довольно просто — пожалуй это самая длинная моя статья в блоге на данный момент. Если что то не понятно — спрашивайте! И если вы нашли ошибки или есть замечания, не молчите 🙂

Теги: function, MySQL, PHP, Авторизация Аутентификация

— Как аутентифицировать пользователя в PHP / MySQL?

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. работы Программирование и связанные с ним технические возможности карьерного роста
  4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
  5. реклама Обратитесь к разработчикам и технологам со всего мира
.Система безопасной регистрации

с PHP и MySQL

Это руководство является продолжением нашего предыдущего учебника Система безопасного входа с PHP и MySQL, мы создадим безопасную регистрационную форму с базовой проверкой.

Пакеты Basic и Advanced включают дополнительные функции и ссылку для загрузки исходного кода.

1. Начало работы

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

1.1. Требования
  • Если у вас нет настройки локального веб-сервера, вам следует загрузить и установить XAMPP. XAMPP — это серверная среда веб-разработки, которая включает в себя все необходимое для веб-разработчиков.

1,2. Что вы узнаете в этом руководстве
  • Дизайн формы — Создайте регистрационную форму с помощью HTML5 и CSS3.
  • Подготовленные SQL-запросы — Как подготовить SQL-запросы для предотвращения SQL-инъекции и вставки новых записей в базу данных MySQL.
  • Базовая проверка — Проверка данных формы, отправляемых на сервер (имя пользователя, пароль и адрес электронной почты).

1,3. Файловая структура и настройка

Теперь нам нужно запустить наш веб-сервер и создать файлы и папки, которые мы собираемся использовать для нашей системы регистрации.

  • Открыть Панель управления XAMPP
  • Рядом с модулем Apache нажмите Пуск
  • Рядом с модулем MySQL нажмите Пуск
  • Перейдите в папку установки XAMPP ( C: \ xampp )
  • Откройте папку htdocs
  • Создайте следующие папки и файлы:

Структура файла

\ — phplogin
| — зарегистрироваться.html
| — style.css
| — register.php
| — activate.php (необязательно)

Каждый файл будет содержать следующее:

  • register.html — Регистрационная форма, созданная с помощью HTML5 и CSS3, этот файл не требует от нас использования PHP, поэтому мы сохраним его как HTML.
  • style.css — Таблица стилей (CSS3) для нашей безопасной формы регистрации.
  • register.php — Проверить данные формы и вставить новую учетную запись в базу данных MySQL.
  • activate.php — Активация учетной записи пользователя с помощью уникального кода (активация по электронной почте).

2. Создание дизайна регистрационной формы

Регистрационная форма будет использоваться посетителями наших веб-сайтов, они могут использовать ее для ввода информации о своей учетной записи, мы будем создавать регистрационную форму с помощью HTML и CSS.

Отредактируйте файл register.html и добавьте следующий код:

  

<Голова>

<Название> Регистрация 


<Тело>

Регистрация

Перейдите по адресу http: // localhost / phplogin / register.html , наша регистрационная форма будет выглядеть следующим образом:

Http: //localhost/phplogin/register.html

,

авторизации пользователей PHP / MySQL

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. работы Программирование и связанные с ним технические возможности карьерного роста
  4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
  5. реклама Обратитесь к разработчикам и технологам со всего мира
.