1

我有一个向自身提交表单的 php 页面。
我想添加一个检查,我可以在其中阻止基本的跨站点伪造。

我的代码:

<?php
session_start();

(...) //some code

$secret = substr(md5(uniqid(rand(), true)), 1, 2);
$_SESSION["secret"] = $secret;
$auth = $secret;

?>

(...)

<form id="form" name="form" action="<?php echo htmlentities($_SERVER[PHP_SELF]); ?>" method="post">

(...)

<input type="hidden" name="id" value="<? echo $auth; ?>" />

(...)

<?php

(...)

//as a debug I just tried to display
echo $_POST["id"];
echo "=";
echo $_SESSION["secret"];

(...)

?>
<div>
</body>
</html>

但两者都id从不secret返回相同的值。
这是为什么?我错过了什么?


更新

所以,我在这里尝试了 Samuel Cook 的回答,正如 Jon Stirling 的评论所建议的那样:

if(!isset($_SESSION["secret"])){
    $secret = substr(md5(uniqid(rand(), true)), 1, 2);
    $_SESSION["secret"] = $secret;
    $auth = $secret;
}

但是现在如果没有$_SESSION["secret"]
页面返回:

<input type="hidden" name="id" value="" />

我明白为什么,因为只有在会话变量存在时才会设置秘密。
有什么建议么?


更新

在生成新的会话密钥之前移动了检查,并且只检查是否有 id 的帖子。现在很好用,谢谢。

4

3 回答 3

0

一旦你打开一个页面 $auth 将生成,提交后我将在隐藏字段中 $_SESSION["secret"] 将更改,因为 $secret 将生成新密钥但 $_POST['id'] 是来自 Post 方法的旧密钥.

于 2012-11-29T18:44:58.447 回答
0

你总是在产生一个新的$secret,因此它总是不同的。您可以检查是否$_SESSION['secret']存在,如果不存在则创建一个新变量。就像是:

if(!isset($_SESSION["secret"])){
    $secret = substr(md5(uniqid(rand(), true)), 1, 2);
    $_SESSION["secret"] = $secret;
    $auth = $secret;
}
于 2012-11-29T18:45:38.280 回答
0

在调试代码执行时,秘密已更改:

echo $_POST["id"]; // previous secret
echo "=";
echo $_SESSION["secret"]; // new secret

只要您在脚本开头(在生成下一个秘密之前)检查匹配项,就可以了。

于 2012-11-29T18:46:04.793 回答