如果我想保护我的网站和用户免受跨站伪造 (CSRF) 攻击,我可以生成一个唯一的令牌$token = md5( time() * rand );
on 每一页有一个形式。令牌在隐藏的输入字段中提交echo '<input type="hidden" name="token" value="'.$token.'">';
并同时存储在会话变量中$_SESSION['token'] = $token;
.
我会检查任何提交的表格上是否有if($_POST['token'] == $_SESSION['token'])
并进行相应的操作。
然而,有些用户可能会同时执行多项任务。这是我在发布此内容时实际上正在做的事情。
在撰写文章时,我会打开不同的窗口/选项卡来可能研究信息或查看有关堆栈溢出的其他一些问题。堆栈溢出让我可以毫无问题地提交表单。
但是,如果我要在我的网站上这样做 - 意思是浏览其他页面,同时仍然撰写帖子/表格 - 我的$token
每次我从网站上拉出不同的页面时都会重新生成。制作隐藏的input
我正在处理并最终想要提交的表单上的令牌不正确,因为它不会匹配$_SESSION['token']
变量不再存在,当我访问不同的页面时已重新生成......
有什么好的想法可以防止这个问题,或者有更好的解决方案来阻止 CSRF?
我希望允许我的用户执行多项任务并希望免受 CSRF 的侵害...
由于单个 CSRF,我也遇到了与您所说的相同的问题,除非他们提交最新页面,否则它会被替换,但如果您使用带有会话的数组,它应该可以解决您的问题。另外,您可能想添加验证码,我推荐 Google 的 Recaptcha。
session_start();
function createToken(){
$token = sha1(uniqid(mt_rand(), true));
$_SESSION['Tokens']['Token'][] = $token;
$_SESSION['Tokens']['Time'][] = time() + (10 * 60); #10 min limit
#you can omit/change this if you want to not limit or extend time limit
return $token;
}
function checkToken($token){
clearTokens();
foreach($_SESSION['Tokens']['Token'] as $key => $value){
if($value === $token){
return true;
}
}
return false;
}
function clearTokens(){
foreach($_SESSION['Tokens']['Time'] as $key => $value){
if($value <= time()){
unset($_SESSION['Tokens']['Token'][$key], $_SESSION['Tokens']['Time'][$key]);
#remove last parameter if you aren't using token time limit
}
}
}
你的HTML:
<input type="hidden" name="token" value="<?php createToken(); ?>">
PHP 令牌检查器
if(isset($_POST['token']) && checkToken($_POST['token'])){
#valid token
}else{
#create error message saying that they tried to repost data or session token expired
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)