Всё работает. Правильно ли я, использовал способ токен? Правильно ли использовал функцию PHP: ini_set('session.use_only_cookies', true); и PHP: output_add_rewrite_var('token', $token); А вот это нормальный способ,на 136 строке? PHP: $tokenstr = strval(date('s')) . $salt; А саму регистрацию нормально сделал? А что мне дают эти токены? А как сделать, что бы после закрытия браузера, сессия сохранялась? PHP: <?php ini_set('session.use_only_cookies', true); session_start(); error_reporting(-1); $host = 'localhost'; $db = 'token'; $user = 'root'; $pass = ''; $charset = 'utf8'; $dsn = "mysql:host=$host; dbname=$db;charset=$charset"; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $user, $pass, $opt); ?> <!DOCTYPE html> <html> <head> <title>Токен</title> <meta charset="utf-8"> <style> .mudak { color: red; font-weight: bold; } </style> </head> <body> <?php if(!empty($_GET['action'])) { if($_GET['action'] == 'exit') { unset($_SESSION['token']); session_destroy(); header('Location: ./index.php'); } } if(!empty($_SESSION['token'])) { echo '<p>Теперь у вас есть полный доступ к сайту <a href="?action=exit">Выход</a></p>'; echo $_SESSION['token']; die(); } else { echo '<p>Авторизируйтесь, что бы увидеть содержимое сайта</p>'; require_once 'auth.php'; echo '<p><strong>Или зарегистрируйтесь</strong></p>'; require_once 'registr.php'; /* * * *******Начало регистрации********* * * */ if(!empty($_POST['reg'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $userExists = "SELECT login FROM users WHERE login = '".$login."'"; $queryUser = $pdo->query($userExists); $queryUser->setFetchMode(PDO::FETCH_ASSOC); if((count($queryUser->fetchAll()) > 0)) { echo '<p>Такой пользователь уже существует<p>'; die(); } else { $newUser = "INSERT INTO users(login, password) VALUES(:login, :password)"; $newUserPrepare = $pdo->prepare($newUser); $newUserPrepare->bindValue(':login', trim($login), PDO::PARAM_STR); $newUserPrepare->bindValue(':password', trim($password), PDO::PARAM_STR); $newUserPrepare->execute(); echo '<p>Регистрация завершена</p>'; } } else { echo '<p class="mudak">Заполните все поля</p>'; } } /* * * *******Конец регистрации********* * * */ /* * * *******Начало авторизации********* * * */ if(!empty($_POST['auth'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $user = "SELECT `login`, `password` FROM users WHERE login = :login AND password = :password"; $resUser = $pdo->prepare($user); $resUser->bindValue(':login', trim($login), PDO::PARAM_STR); $resUser->bindValue(':password', trim($password), PDO::PARAM_STR); $resUser->execute(); $resUser2 = $resUser->fetchAll(); if(count($resUser2) === 0){ die('Неверный логин или пароль'); } else { $salt = $login; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $_SESSION['token'] = $token; $_SESSION['user'] = $login; output_add_rewrite_var('token', $token); header('Location: ./index.php'); } } else { echo '<p class="mudak">Заполните все поля</p>'; } } /* * * *******Конец авторизации********* * * */ } ?> </body> </html>
Так, как ты написал, токены бесполезны. От них есть толк, если потом их везде за собой таскать по запросам, и каждый раз проверять соответствие токена, пришедшего в запросе, тому, что в сессии. Защищает от CSRF-атак. Записать в базу и в куку случайную строку, сравнивать, если пришла правильная кука - авторизировать пользователя.
А зачем в базу записывать? --- Добавлено --- не понял, а потом эту строку каждый раз записывать в БД?
Я вот так сделал, только теперь, при каждом обновлении страницы, меняется название сессии PHP: <?php ini_set('session.use_only_cookies', true); session_start(); error_reporting(-1); $host = 'localhost'; $db = 'token'; $user = 'root'; $pass = ''; $charset = 'utf8'; $dsn = "mysql:host=$host; dbname=$db;charset=$charset"; $opt = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, ]; $pdo = new PDO($dsn, $user, $pass, $opt); ?> <!DOCTYPE html> <html> <head> <title>Токен</title> <meta charset="utf-8"> <style> .mudak { color: red; font-weight: bold; } </style> </head> <body> <?php if(!empty($_GET['action'])) { if($_GET['action'] == 'exit') { unset($_SESSION['token']); session_destroy(); setcookie ("user", "", time()-3600); header('Location: ./index.php'); } } if(!empty($_SESSION['token']) || !empty($_COOKIE['user'])) { $sql = "SELECT login, password FROM users WHERE randomSTR = '" . $_COOKIE['user'] . "'"; $queryUser = $pdo->query($sql); $queryUser->setFetchMode(PDO::FETCH_ASSOC); $userArray = $queryUser->fetchAll(); if(!empty($userArray[0]['login'])) { $login = $userArray[0]['login']; $salt = $login; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $_SESSION['token'] = $token; output_add_rewrite_var('token', $token); } else { die('<p>Авторизируйтесь, что бы увидеть содержимое сайта</p>'); } echo '<p>Теперь у вас есть полный доступ к сайту <a href="?action=exit">Выход</a></p>'; echo $_SESSION['token']; } else { echo '<p>Авторизируйтесь, что бы увидеть содержимое сайта</p>'; require_once 'auth.php'; echo '<p><strong>Или зарегистрируйтесь</strong></p>'; require_once 'registr.php'; /* * * *******Начало регистрации********* * * */ if(!empty($_POST['reg'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $userExists = "SELECT login FROM users WHERE login = '".$login."'"; $queryUser = $pdo->query($userExists); $queryUser->setFetchMode(PDO::FETCH_ASSOC); if((count($queryUser->fetchAll()) > 0)) { echo '<p>Такой пользователь уже существует<p>'; die(); } else { $newUser = "INSERT INTO users(login, password) VALUES(:login, :password)"; $newUserPrepare = $pdo->prepare($newUser); $newUserPrepare->bindValue(':login', trim($login), PDO::PARAM_STR); $newUserPrepare->bindValue(':password', trim($password), PDO::PARAM_STR); $newUserPrepare->execute(); echo '<p>Регистрация завершена</p>'; } } else { echo '<p class="mudak">Заполните все поля</p>'; } } /* * * *******Конец регистрации********* * * */ /* * * *******Начало авторизации********* * * */ if(!empty($_POST['auth'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $user = "SELECT `login`, `password` FROM users WHERE login = :login AND password = :password"; $resUser = $pdo->prepare($user); $resUser->bindValue(':login', trim($login), PDO::PARAM_STR); $resUser->bindValue(':password', trim($password), PDO::PARAM_STR); $resUser->execute(); $resUser2 = $resUser->fetchAll(); if(count($resUser2) === 0){ die('Неверный логин или пароль'); } else { $arr = ['f', 3, 'g', 'bd', 5, 'p', 'k', 'n', 'v', 'w', 33, 'c', 'o']; shuffle($arr); $str = ''; foreach($arr as $k) { $str .= $k; } $sql = "UPDATE users SET randomSTR ='" . $str . "' WHERE login = '" . $login . "'"; $queryToket = $pdo->query($sql); setcookie ("user", $str, time()+3600); $salt = $login; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $_SESSION['token'] = $token; output_add_rewrite_var('token', $token); header('Location: ./index.php'); } } else { echo '<p class="mudak">Заполните все поля</p>'; } } /* * * *******Конец авторизации********* * * */ } ?> </body> </html> --- Добавлено --- Изменил на это PHP: if(empty($_SESSION['token']) && !empty($_COOKIE['user'])) { $sql = "SELECT login, password FROM users WHERE randomSTR = '" . $_COOKIE['user'] . "'"; $queryUser = $pdo->query($sql); $queryUser->setFetchMode(PDO::FETCH_ASSOC); $userArray = $queryUser->fetchAll(); if(!empty($userArray[0]['login'])) { $login = $userArray[0]['login']; $salt = $login; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $_SESSION['token'] = $token; output_add_rewrite_var('token', $token); } } if(!empty($_SESSION['token']) ) { echo '<p>Теперь у вас есть полный доступ к сайту <a href="?action=exit">Выход</a></p>'; echo $_SESSION['token']; } --- Добавлено --- Но теперь получается, хакер может подставлять значение в куку и если оно совпадёт, то произойдёт авторизация
Вот так сделал удаление статьи, с помощью токена, правильно ли PHP: <?php echo '<p>Добавить статью</p>'; require_once 'add.php'; echo '<p>Мои статьи</p>'; $myArticle = "SELECT article.id, title, user_id FROM article INNER JOIN users ON article.user_id = " . $_SESSION['id'] . " GROUP BY article.title"; $sth = $pdo->query($myArticle); $sth->setFetchMode(PDO::FETCH_ASSOC); $userArticle = $sth->fetchAll(); echo '<pre>'; print_r($userArticle); echo '</pre>'; echo '<table>'; echo '<tr>'; echo '<td>Название</td>'; echo '<td>Действие</td>'; echo '</tr>'; foreach($userArticle as $key) { echo '<tr>'; echo '<td>'.$key['title'].'</td>'; echo '<td><form method="post"> <input type="hidden" name="id-title" value="'.$key['id'].'"> <input type="hidden" name="id-user" value="'.$key['user_id'].'"> <input type="submit" name="del-article" value="Удалить"> </form></td>'; echo '</tr>'; } echo '<table>'; if(!empty($_POST['del-article'])) { $sql = "SELECT article.id, `title`, `user_id`, users.randomSTR FROM article INNER JOIN users ON article.id = '".$_POST['id-title']."' AND article.user_id = '".$_POST['id-user']."' AND users.randomSTR = '".$_COOKIE['user']."' GROUP BY article.title"; $sth = $pdo->query($sql); $sth->setFetchMode(PDO::FETCH_ASSOC); $delArticle = $sth->fetchAll(); if(count($delArticle[0]) > 1) { $sqlDelArticle = "DELETE FROM article WHERE id = :id"; $del = $pdo->prepare($sqlDelArticle); $del->bindValue(':id', $_POST['id-title'], PDO::PARAM_INT); $del->execute(); echo 'Удалено'; } else { echo 'Ошибка удаления'; } /* echo '<pre>'; print_r($delArticle); echo '<pre>'; echo count($delArticle[0]); */ } ///SELECT article.id, title, user_id FROM article LEFT JOIN users ON article.user_id = 3 GROUP BY article.title;
Нафига ты токен создавал, если нигде его не проверяешь? --- Добавлено --- Весь смысл в том, что PHP: if ($_GET["token"] !== $_SESSION["token"]) { unset($_SESSION["user_id"]); header("Location: /login.php"); die; } Без этого пользы от его генерации нету. --- Добавлено --- Это вообще бред. У тебя удалять могут только те, кто поставил галочку "запомнить меня"? Или у тебя все запоминаются? Ты путаешь назначения инструментов - случайной строки в куках (для того, чтобы пользователь автоматом перелогинивался при каждом заходе на сайт) и токена сессии (для того, чтобы никто не подменил запрос)
Пока что, все запоминаются. Как пользоваться токенами, я так и не понял --- Добавлено --- А сейчас же, уже не могут подменить запрос
Изменил запись токена в регистрации и в авторизации Так правильно? Удаление сделал по условию PHP: if(!empty($_POST['del-article'])) { if($_POST['token'] == $_SESSION['token']) { PHP: /* * * *******Начало регистрации********* * * */ if(!empty($_POST['reg'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $userExists = "SELECT login FROM users WHERE login = '".$login."'"; $queryUser = $pdo->query($userExists); $queryUser->setFetchMode(PDO::FETCH_ASSOC); if((count($queryUser->fetchAll()) > 0)) { echo '<p>Такой пользователь уже существует<p>'; die(); } else { $newUser = "INSERT INTO users(login, password) VALUES(:login, :password)"; $newUserPrepare = $pdo->prepare($newUser); $newUserPrepare->bindValue(':login', trim($login), PDO::PARAM_STR); $newUserPrepare->bindValue(':password', trim($password), PDO::PARAM_STR); $newUserPrepare->execute(); echo '<p>Регистрация завершена</p>'; } } else { echo '<p class="mudak">Заполните все поля</p>'; } } /* * * *******Конец регистрации********* * * */ /* * * *******Начало авторизации********* * * */ if(!empty($_POST['auth'])) { if(!empty($_POST['login']) && !empty($_POST['password'])) { $login = $_POST['login']; $secret = 'hhJNE63'; $password = md5($_POST['password'].$secret); $user = "SELECT `id`, `login`, `password` FROM users WHERE login = :login AND password = :password"; $resUser = $pdo->prepare($user); $resUser->bindValue(':login', trim($login), PDO::PARAM_STR); $resUser->bindValue(':password', trim($password), PDO::PARAM_STR); $resUser->execute(); $resUser2 = $resUser->fetchAll(); $userId = $resUser2[0]['id']; if(count($resUser2) === 0){ die('Неверный логин или пароль'); } else { $salt = $login; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $sql = "UPDATE users SET token ='" . $token . "' WHERE login = '" . $login . "'"; $queryToket = $pdo->query($sql); setcookie ("user", $token, time()+3600); $_SESSION['token'] = $token; $_SESSION['user'] = $login; $_SESSION['id'] = $userId; output_add_rewrite_var('token', $token); header('Location: ./index.php'); } } PHP: <?php echo '<p>Добавить статью</p>'; require_once 'add.php'; echo '<p>Мои статьи</p>'; $myArticle = "SELECT article.id, title, user_id FROM article INNER JOIN users ON article.user_id = " . $_SESSION['id'] . " GROUP BY article.title"; $sth = $pdo->query($myArticle); $sth->setFetchMode(PDO::FETCH_ASSOC); $userArticle = $sth->fetchAll(); echo '<table>'; echo '<tr>'; echo '<td>Название</td>'; echo '<td>Действие</td>'; echo '</tr>'; foreach($userArticle as $key) { echo '<tr>'; echo '<td>'.$key['title'].'</td>'; echo '<td><form method="post"> <input type="hidden" name="id-title" value="'.$key['id'].'"> <input type="hidden" name="token" value="' .$_SESSION['token'].'"> <input type="submit" name="del-article" value="Удалить"> </form></td>'; echo '</tr>'; } echo '<table>'; if(!empty($_POST['del-article'])) { if($_POST['token'] == $_SESSION['token']) { $sql = "SELECT article.id, `title`, `user_id`, users.id, users.token FROM article INNER JOIN users ON article.id = '".$_POST['id-title']."' AND article.user_id = '".$_SESSION['id']."' AND users.token = '".$_COOKIE['user']."' AND users.id = '".$_SESSION['id']."' GROUP BY article.title"; $sth = $pdo->query($sql); $sth->setFetchMode(PDO::FETCH_ASSOC); $delArticle = $sth->fetchAll(); if(count($delArticle[0]) > 1) { $sqlDelArticle = "DELETE FROM article WHERE id = :id"; $del = $pdo->prepare($sqlDelArticle); $del->bindValue(':id', $_POST['id-title'], PDO::PARAM_INT); $del->execute(); echo 'Удалено'; } else { echo 'Ошибка удаления'; } } }
Вот это уже больше похоже на правду. ТОлько строгое равенство сделай Но вообще, если ты уж завёл token в сессии, таскай его вообще во всех ссылках и проверяй в каждом запросе. Строго говоря, если я у тебя авторизировался, то во все ссылки на сайте добавляется example.com/url?token=jfsjfghlskjghsdlljhjhlafd, и каждый раз, помимо авторизации пользователя, ты проверяешь, передан ли этот токен в гете. И если не передан, разавторизируешь сразу. Можно ещё для них всякие сроки жизни придумывать и т.п.
Сделал регистрацию, что бы нельзя было допустить sql инъекцию, нормально ли? PHP: function registr($login, $password, $email) { $input_email = filter_var($email, FILTER_VALIDATE_EMAIL); $pass = password_hash($passwod, PASSWORD_DEFAULT); if($input_email === false) { echo '<p>Введите правильно email</p>'; die(); } $newLogin = str_replace(";","",$login); $newLogin2 = str_replace(")","",$newLogin); $newLogin3 = str_replace("'","",$newLogin2); $userExists = "SELECT DISTINCT login FROM users WHERE login = '".$newLogin3."'"; $queryUser = $this->db->query($userExists); $queryUser->setFetchMode(PDO::FETCH_ASSOC); if((count($queryUser->fetchAll()) > 0)) { echo '<p>Такой пользователь уже существует</p>'; die(); } else { $newUser = "INSERT INTO users(login, password, email) VALUES(:login, :password, :email)"; $newUserPrepare = $this->db->prepare($newUser); $newUserPrepare->bindValue(':login', trim($newLogin3), PDO::PARAM_STR); $newUserPrepare->bindValue(':password', trim($pass), PDO::PARAM_STR); $newUserPrepare->bindValue(':email', trim($input_email), PDO::PARAM_STR); $newUserPrepare->execute(); echo '<p>Регистрация завершена</p>'; echo '<p><a href="?index">Перейти на главную страницу сайта</a></p>'; } }
Сделал авторизацию, с помощью password_verify и после авторизации, сразу добавил токен в GET параметр, так правильно? PHP: function Login($login, $password) { $newLogin = str_replace(";","",$login); $newLogin2 = str_replace(")","",$newLogin); $newLogin3 = str_replace("'","",$newLogin2); $sqlPass = "SELECT DISTINCT `id`, `login`, `password` FROM users WHERE login = :log"; $resPass = $this->db->prepare($sqlPass); $resPass->bindValue(':log', trim($newLogin3), PDO::PARAM_STR); $resPass->execute(); $allRes = $resPass->fetchAll(); $needPassword = $allRes[0]['password']; $userId = $allRes[0]['id']; $userLogin = $allRes[0]['login']; $hash = $needPassword; if (password_verify($password, $hash)) { $salt = 'slovo'; $tokenstr = strval(date('s')) . $salt; $token = md5($tokenstr); $sql = "UPDATE users SET token ='" . $token . "' WHERE login = :log2"; $queryToket = $this->db->prepare($sql); $queryToket->bindValue(':log2', trim($newLogin3), PDO::PARAM_STR); $queryToket->execute(); setcookie ("user", $token, time()+604800); $_SESSION['token'] = $token; $_SESSION['userPdd'] = $userLogin; $_SESSION['id'] = $userId; output_add_rewrite_var('token', $token); header('Location: ./index.php?token='.$_SESSION['token']); } else { die('Неверный логин или пароль'); } }