Как проверить токен без базы данных?

Я разместил два домена на одном сервере, домен A и домен B.

Домен A сгенерирует уникальный токен доступа к содержимому домена B.

Домен А

<?php
  //http://php.net/manual/en/function.phpversion.php
  //echo 'Version of PHP: ' . phpversion();

  session_start();
  //$expiry_timestamp = time() + $expiry;
  //https://davidwalsh.name/random_bytes //https://secure.php.net/random_bytes
  //$token = bin2hex(random_bytes(64)); 
  $token = bin2hex(openssl_random_pseudo_bytes(64));
  //$time_token = 12000;
  //$time_token = srand(floor(time() / $time_token));
  //echo $token;
  $_SESSION['token']=$token;
?>

<html>
    <head>
    </head>

    <body>  
        <a href= "domainB.com/content1.php?token=<?php echo $_SESSION['token']; ?>">Content 1</a>
    </body>
</html>

Процесс создания токена кажется правильным, его было легко сгенерировать.

Теперь возникает моя проблема, как я могу проверить сгенерированный токен из домена A в домен B ?. Сгенерированный токен должен быть действительным только для контента, который сгенерировал токен, токен не должен быть действительным для другого контента, токен должен быть уникальным, чтобы пользователь не мог предоставить доступ другому пользователю, если он не с его или ее компьютера, токен должен быть действителен только в течение 4 часов доступа, после 4 часов токен больше не будет действителен для отображения содержимого, необходимо сгенерировать новый токен для повторного доступа.

Можно ли выполнить этот процесс с помощью файла cookie без использования базы данных?

Возможно, идентифицировать оба домена A и B с помощью ключа, что-то в этом роде

$APP_SECRET_KEY = "key code secret";

Вы не хотите использовать базу данных, но можете ли вы создать файл, например, для проверки данных? Вы генерируете токен из домена A -> вы создаете файл с данными пользователя + токена -> домен B проверяете этот файл -> через 4 часа вы стираете файл

Mickaël Leger 10.08.2018 15:03

Достаточно легко передать токен из одного домена в другой, но вам понадобится какой-то общий ресурс на стороне сервера (чтобы с ним нельзя было повозиться), доступный для обоих доменов - это может быть общий файловый сервер, если вы не используете базу данных.

CD001 10.08.2018 15:03

@ CD001 вы можете объяснить мне, что мне нужно изменить на моем сервере?

user10208455 10.08.2018 15:07

@MickaelLeger Выглядит так же просто, как вы говорите, но как этот процесс должен быть реализован :(

user10208455 10.08.2018 15:09

Там, где я работаю, мы используем AWS s3 (aws.amazon.com/fr/s3), очень легко создать файл, загрузить файл, прочитать файл или удалить файл. Я уверен, что есть другой способ сделать это, но не знаю их, извините: s

Mickaël Leger 10.08.2018 15:21

Трудно сказать, не зная вашей точной архитектуры - используете ли вы оба веб-сервера в одной файловой системе? Например, одна установка Apache запускает 2 VirtualHosts? Если это так, должно быть просто сохранить токен в /tmp (скажем, используя file_put_contents()). Затем, чтобы убедиться, что домен B получает правильный токен, вы можете передать параметр как что-то вроде token=asdasd:qweqwe123, где asdasd будет (случайно сгенерированным) именем файла в /tmp, а qweqwe132 будет значением токена (в файле). Немного грубовато по краям, но это основная предпосылка.

CD001 10.08.2018 15:41

@ CD001 эта информация служит вам: я нанял хостинг-хостинг, на этом сервере используются два домена, структура - это то, что у меня есть в вопросе, это то, что я имел в виду и сделал, но самая большая проблема - это проверка .

user10208455 10.08.2018 18:25

почему бы вам не сохранить токен в файл и не прочитать его в домене B?

lot 14.08.2018 19:45
6
8
1 978
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Веб-токен Json (JWT), кажется, соответствует вашим требованиям. Оба приложения используют один секретный ключ для обмена токенами с зашифрованными данными друг с другом.

Пример использования:

  • Пусть секретный ключ $secret="secret"
  • Необработанные данные сообщают нам временную метку Unix, когда генерируется токен (поле iat), идентификатор пользователя (поле sub) и идентификатор контента (поле content).
$data = [
  "sub" => "1234567890",
  "iat" => 1516239022,
  "content" => 1
];

Приложение A кодирует необработанные данные секретным ключом с использованием алгоритма HS256 ($token = jwt_encode($raw, 'HS256', $secret)). Выход $token будет:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJjb250ZW50IjoxfQ.idM7d2fgmJVk3WjANwG-Gt6sY0lyE3eTvpKRpwITHRs

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

Токен отправляется в приложение B. Это приложение декодирует токен с использованием того же алгоритма и общего секретного ключа ($raw = jwt_decode($token, 'HS256', $secret)). Необработанные данные будут доступны в приложении B. Эти данные можно использовать для проверки токена:

  • Прочтите идентификатор пользователя из поля sub и проверьте его правильность
  • Прочтите идентификатор содержимого из поля content и проверьте его правильность
  • Прочтите метку времени, когда токен генерируется из поля iat, и проверьте, был ли он в последние 4 часа.

Для вас есть несколькоБиблиотеки PHPосуществлятьJWT.

Без сторонних библиотек сделать это невозможно :(

user10208455 10.08.2018 18:22

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

Hieu Le 11.08.2018 03:19

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

user10208455 11.08.2018 07:35
Ответ принят как подходящий

Хорошим подходом здесь является использование общего секретного ключа.

Я обычно использую HMAC, когда мне нужно сгенерировать и проверить токен (например, проверка электронной почты) и не хочу хранить его в БД. Плюс HMAC встроен в PHP, поэтому библиотека здесь не нужна.

Идея состоит в том, что поверх ваших данных вы добавляете подпись, чтобы убедиться, что этот токен был создан вашим приложением в домене A. Вы генерируете токен таким же образом снова в домене B, чтобы проверить его.

Пример:

Общая функция для генерации токена:

function buildVerificationToken($expires, $content)
{
    // Same function on both domains
    $APP_SECRET_KEY = 'key code secret';  // Maybe move that out of source code

    $tokenData = [
        'expires' => $expires, // Include it in signatur generation to prevent user from changing it in URL
        'content' => $content, // Create different token for different content
        'ip' => $_SERVER['REMOTE_ADDR'], // Identify the browser to make it not shareable. Best approach I could think of for this part.
    ];

    $serialized = json_encode($tokenData);

    return hash_hmac('sha256', $serialized, $APP_SECRET_KEY);
}

Сгенерируйте токен в Домене A:

<?php
$expires = time() + (4 * 3600); // +4h
?>
<a href= "domainB.com/content1.php?expires=<?php echo $expires; ?>&token=<?php echo buildVerificationToken($expires, 'content1'); ?>">Content 1</a>

Проверьте это в домене B:

$providedExpires = (int) $_GET['expires'];
$providedToken = $_GET['token'];

$verificationToken = buildVerificationToken($providedExpires, 'content1'); // Build token the same way

if (!hash_equals($verificationToken, $providedToken)) { // hash_equals instead of string comparison to prevent timing attacks
    // User provided forged token, token for another content, or another IP
    die('Bad token'); // However you want to handle this
}

if (time() > $providedExpires) { // Check expiry time. We can trust the user did not modify it as we checked the HMAC hash
    die('Token expired'); // However you want to handle this
}

// User is allowed to see content1

Другие вопросы по теме