Hi, Habr! In the light of the information on the security of large portals' accounts, which appeared recently, I decided to revise a little cookie authorization in my projects. First of all, he was questioned with a predilection of Google on the topic of ready-made solutions. Nothing sensible was found, although it may be that I do not know how to use the search. After that, I decided to see what they actually write about how to chew cookies correctly. To my surprise, there were no limits when most of the articles from the category of “bad advice”, and what I read more than 5 years ago.CREATE TABLE `user_auth_cookies` ( `key` char(32) NOT NULL, `user_id` int(10) unsigned NOT NULL, `logged_in` datetime NOT NULL, PRIMARY KEY (`key`), KEY `user_id` (`user_id`), KEY `logged_in` (`logged_in`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; $db = new mysqli('localhost', 'test', '', 'test'); if ($db->connect_errno) die(' MySQL: ('.$db->connect_errno.') '.$db->connect_error); // define('DOMAIN', ($_SERVER['HTTP_HOST'] !== 'localhost' ? $_SERVER['HTTP_HOST'] : false)); // . localhost, false ( ) define('AUTO_AUTH_URL', '/auth/auto'); // define('AUTH_URL', '/auth'); // define('AUTH_COOKIE_DURATION', 20); // , define('USE_HTTPS', false); // HTTPS ( ) class User { private $_id; public $isGuest = true; public $name = ''; public function __construct() { GLOBAL $db; if (!isset($_SESSION['user']) || $_SESSION['user']['ip'] !== $_SERVER['REMOTE_ADDR']) return; $query = 'SELECT * FROM users WHERE `id` = '.(int)$_SESSION['user']['id']; if (($res = $db->query($query)) !== false && $res->num_rows) { $user = $res->fetch_assoc(); $this->_id = $user['id']; $this->name = $user['name']; $this->isGuest = false; if (isset($_SESSION['last_request'])) { $_POST = $_SESSION['last_request']['data']; unset($_SESSION['last_request']); } } else { unset($_SESSION['user']); } } public function getId() { return $this->_id; } } class Auth { public static function loginRequired() { $_SESSION['last_request'] = array( 'url' => $_SERVER['REQUEST_URI'], 'data' => $_POST ); header('Location: '.AUTO_AUTH_URL); die('...'); } public static function login($login, $password, $remember = false) { GLOBAL $db; $query = "SELECT * FROM users WHERE `login` = '".$db->real_escape_string($login)."';"; if (($res = $db->query($query)) === false || !$res->num_rows) return false; $user = $res->fetch_assoc(); // , if ($user['password'] !== md5($login.md5($password))) return false; if ($remember) { do { $key = md5(mcrypt_create_iv(30)); $query = "SELECT COUNT(*) AS `cnt` FROM user_auth_cookies WHERE `key` = '".$key."';"; $count = 0; if (($res = $db->query($query)) !== false && $res->num_rows) { $row = $res->fetch_assoc(); $count = (int)$row['cnt']; } else die(' .'); } while ($count > 0); $db->query("INSERT INTO user_auth_cookies VALUES ('".$key."', ".$user['id'].", NOW());"); setcookie('key', $key, strtotime('+'.AUTH_COOKIE_DURATION.' days'), AUTO_AUTH_URL, DOMAIN, USE_HTTPS, true); } $_SESSION['user'] = array( 'id' => $user['id'], 'ip' => $_SERVER['REMOTE_ADDR'], ); return true; } public static function loginByCookie() { GLOBAL $db; $location = AUTH_URL; if (isset($_COOKIE['key'])) { $query = "SELECT user_id FROM user_auth_cookies WHERE `key` = '".$db->real_escape_string($_COOKIE['key'])."';"; if (($res = $db->query($query)) !== false && $res->num_rows) { $row = $res->fetch_assoc(); $_SESSION['user'] = array( 'id' => $row['user_id'], 'ip' => $_SERVER['REMOTE_ADDR'] ); $location = '/'; if (isset($_SESSION['last_request'])) $location = $_SESSION['last_request']['url']; } } header('X-Frame-Options: DENY'); // FRAME/IFRAME header('Location: '.$location); die('...'); } public static function logout() { if (!isset($_SESSION['user'])) return; if (mb_strlen($_SESSION['user']['key']) === 32) $db->query("DELETE FROM user_auth_cookies WHERE `key` = '".$db->real_escape_string($_SESSION['user']['key'])."';"); setcookie('key', '', 0, AUTO_AUTH_URL, DOMAIN, USE_HTTPS, true); unset($_SESSION['user']); header('Location: /'); die('...'); } } …… $user = new User(); if ($user->isGuest) Auth::loginRequired(); …… …… if (isset($_POST['login']) && Auth::login($_POST['login'], $_POST['password'], !!$_POST['remember_me'])) { $location = '/'; if (isset($_SESSION['last_request'])) $location = $_SESSION['last_request']['url']; header('Location: '.$location); die('...'); } …… <ifModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-U RewriteRule ^.*$ index.php [L,QSA] </ifModule> …… $db->query("DELETE FROM user_auth_cookies WHERE `logged_in` < DATE_SUB(NOW(), INTERVAL ".AUTH_COOKIE_DURATION." DAYS);"); …… …… if (isset($_POST['signout_all']) { $db->query("DELETE FROM user_auth_cookies WHERE `user_id` = ".$user->getId()); Auth::logout(); } …… Source: https://habr.com/ru/post/210416/
All Articles