Я читаю книгу Криса Шиффлета «Essential PHP Security». В CSRF есть глава, где автор рекомендует использовать токен для предотвращения CSRF. Код в книге говорит о добавлении токена в форму, которую мы используем
<?php
session_start();
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
?>
<form action="buy.php" method="POST">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<p>
Item:
<select name="item">
<option name="pen">pen</option>
<option name="pencil">pencil</option>
</select><br />
Quantity: <input type="text" name="quantity" /><br />
<input type="submit" value="Buy" />
</p>
</form>
и токен можно проверить с помощью простого условного оператора.
<?php
if (isset($_SESSION['token']) && $_POST['token']== $_SESSION['token'])
{
echo $_POST['token'];
echo "form passed";
}
Но приведенный выше код, похоже, не работает. Сообщение «Форма пройдена» не отображается. Что не так с приведенным выше кодом? Первый набор кодов генерирует токен, но сообщения об успехе нет.
Вам нужно добавить session_start();
вершина этого кода в buy.php
, Пример…
session_start();
if (isset($_SESSION['token']) && $_POST['token']== $_SESSION['token'])
{
echo $_POST['token'];
echo "form passed";
}
Я предложу вам сделать это эффективно и функционально:
session_start();
function generate_token(){
$token = uniqid(rand(), true);
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
}//avoid putting script at bottom until required
if($_SERVER['REQUEST_METHOD']=='POST' && !empty($_POST)){
if(isset($_SESSION['token']) && isset($_SESSION['token_time']) &&
isset($_POST['token']))
{
if($_SESSION['token'] == $_POST['token'])
{
$timestamp_ancien = time() - (15*60);
//Si le jeton n'est pas expiré
if($_SESSION['token_time'] >= $timestamp_ancien)
{
//here Instruction
generate_token();//for next call}else{echo"error3";}
}else{echo"error2";}
}else{echo"error1";}
}
generate_token();
Причина: Вы можете поместить эту функцию в любое место в вашем проекте и включить или потребовать, чтобы файл использовал этот код, не записывая его везде.