跨站请求伪造CSRF的防御:One-Time Tokens(不同的表单包含一个不同的伪随机值)
在实现One-Time
Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提
交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单
都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
以下我的实现:
1).先是令牌生成函数(gen_token()):
function gen_token() {
//这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
$token = md5(uniqid(rand(), true));
return $token;
}
2).然后是Session令牌生成函数(gen_stoken()):
function gen_stoken() {
$pToken = "";
if($_SESSION[STOKEN_NAME] == $pToken){
//没有值,赋新值
$_SESSION[STOKEN_NAME] = gen_token();
}
else{
//继续使用旧的值
}
}
?>
3).WEB表单生成隐藏输入域的函数:
function gen_input() {
gen_stoken();
echo “
value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;
}
?>
4).WEB表单结构:
session_start();
include(”functions.php”);
?>
gen_input(); ?>
5).服务端核对令牌:
这个很简单,这里就不再啰嗦了。
上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。