我正在做表单验证器(使用令牌)。 Page基于smarty。所以在课堂文章中我有以下功能:
public static function getToken(){
self::$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = self::$token;
}
然后在.tpl文件中我插入了这样的值:
<input type="hidden" name="token" value="{Articles::$token}">
提交表单后,检查将在index.php中运行:
if(isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
Articles::addComment($item, $_POST['name'], $_POST['email'], $_POST['comment']);
}
问题在于我获得了不同的令牌。例如,我回显了$_SESSION['token']
并将其与表单中的值进行了比较(查看源代码)。
提交后,我试图回显值($_SESSION ['token']
和$_POST ['token])
,它们也是不同的。显然,表格没有提交。
答案 0 :(得分:0)
无需为用户以1:1的比例映射CSRF令牌。如果您在页面上有多个表单怎么办?如果用户打开了多个浏览器窗口会怎样?
定义要存储0..n
令牌的内容,为它们设置合理的有效期,[可选]定义它们有效的。例如:
class Token {
protected $id, $expiry;
public function __construct($expiry=300, $id=NULL) {
$this->expiry = time() + $expiry;
if( is_null($id) ) {
// actual secure ID generation.
$this->id = bin2hex(random_bytes(32));
} else {
$this->id = $id;
}
}
public function getID() {
return $id;
}
public function isValid() {
return time() < $expiry;
}
}
class YourApp {
public function newToken() {
$token = new Token();
$_SESSION['tokens'][$token->getID()] = $token;
return $token
}
public function checkToken($token_id) {
if( key_exists($token_id, $_SESSION['tokens']) ) {
$cur = $_SESSION['tokens'][$token_id];
unset($_SESSION['tokens'][$token_id]; // single use only!
return $cur->isValid();
} else {
return false;
}
}
public function flushOldTokens() {
$_SESSION['tokens'] = array_filter(
$_SESSION['tokens'],
function($t){return $t->isValid();}
);
}
}