Раз оказалось, что аудитории небезразлична такая тема, как создание одноразовых (работающих в течение некоторого времени) ссылок, позволяющих идентифицировать пользователя.
А особенно в свете того, что я считаю подобное решение (которое я опубликую ниже) приемлемее — решил написать, как решение этой задачи вижу я:
Хранится всё в базе. Mysql только потому, что она сейчас есть под рукой. Для постгре, оракла и sql server решение будет на 99% аналогичным.
Таблица для хранения:
Ну и теперь сам класс + пример работы с ним. В примере мы сначала создаём токен сроком до 31 декабря сего года, а затем его же получаем.
PS: код писался «на коленке» просто в качестве ответа на топик habrahabr.ru/blogs/php/109421
PPS: сразу хотелось бы уточнить по поводу md5() — эта функция в данном контексте не добавляет никаких «дыр», это просто способ получить хэш. При желании можно заменить на sha1(), или любой другой по желанию. Главная идея в том, что не нужно завязываться на юзерские данные.
А особенно в свете того, что я считаю подобное решение (которое я опубликую ниже) приемлемее — решил написать, как решение этой задачи вижу я:
Хранится всё в базе. Mysql только потому, что она сейчас есть под рукой. Для постгре, оракла и sql server решение будет на 99% аналогичным.
Таблица для хранения:
Copy Source | Copy HTML
- CREATE TABLE test.one_time_auth(
- token CHAR (32),
- user_id INT (11) UNSIGNED NOT NULL,
- expire DATETIME DEFAULT NULL,
- PRIMARY KEY (token)
- )
- ENGINE = INNODB
Ну и теперь сам класс + пример работы с ним. В примере мы сначала создаём токен сроком до 31 декабря сего года, а затем его же получаем.
Copy Source | Copy HTML
- <?php
-
- $db = new PDO('mysql:host=127.0.0.1;dbname=test', 'root');
- $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- $auth = new one_time_auth($db);
- $token = $auth->remember(10, '2010-12-31');
-
- $user_id = $auth->remind($token);
- echo $user_id;
-
- class one_time_auth
- {
- /**<br/> * @var PDO<br/> */
- private $db;
-
- public function __construct(PDO $db)
- {
- $this->db = $db;
- }
-
- public function remember($user_id, $expire = null)
- {
- $sql = 'INSERT INTO one_time_auth (token, user_id, expire) VALUES (:token, :user_id, :expire)';
-
- $stmt = $this->db->prepare($sql);
-
- while (true) {
- try {
- $stmt->execute(array(
- ':token' => $token = $this->generateToken(),
- 'user_id' => $user_id,
- 'expire' => $expire
- ));
- break;
- } catch (PDOException $e) {}
- }
-
- return $token;
- }
-
- public function remind($token)
- {
- $sql = 'SELECT user_id<br/> FROM one_time_auth<br/> WHERE token = :token<br/> AND (expire IS NULL OR expire <= NOW())<br/> LIMIT 1';
-
- $stmt = $this->db->prepare($sql);
-
- $stmt->execute(array('token' => $token));
-
- if ($row = $stmt->fetch()) {
- $stmt = $this->db->prepare('DELETE FROM one_time_auth WHERE token = :token');
- $stmt->execute(array('token' => $token));
-
- return $row['user_id'];
- }
- }
-
- private function generateToken()
- {
- return md5(uniqid('', true));
- }
- }
PS: код писался «на коленке» просто в качестве ответа на топик habrahabr.ru/blogs/php/109421
PPS: сразу хотелось бы уточнить по поводу md5() — эта функция в данном контексте не добавляет никаких «дыр», это просто способ получить хэш. При желании можно заменить на sha1(), или любой другой по желанию. Главная идея в том, что не нужно завязываться на юзерские данные.