这个方法个人觉得已经可以杜绝99%的CSRF攻击了,那还有1%呢....由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,这另外的1%。一般的攻击者看到有需要算Hash值,基本都会放弃了,某些除外,所以如果需要的杜绝,这个不是好的方法。
  (2).验证码
  这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
  (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
  在实现One-Time Tokens时,需要注意一点:是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。
  以下我的实现:
  1).先是令牌生成函数(gen_token()):
  <?php
  function gen_token() {
  //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。
  //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》
  $token = md5(uniqid(rand(), true));
  return $token;
  }
  2).然后是Session令牌生成函数(gen_stoken()):
  <?php
  function gen_stoken() {
  $pToken = "";
  if($_SESSION[STOKEN_NAME]  == $pToken){
  //没有值,赋新值
  $_SESSION[STOKEN_NAME] = gen_token();
  }
  else{
  //继续使用旧的值
  }
  }
  ?>
  3).WEB表单生成隐藏输入域的函数:
  <?php
  function gen_input() {
  gen_stoken();
  echo “<input type=”hidden” name=”" . FTOKEN_NAME . “”
  value=”" . $_SESSION[STOKEN_NAME] . “”> “;
  }
  ?>
  4).WEB表单结构:
  <?php
  session_start();
  include(”functions.php”);
  ?>
  <form method=”POST” action=”transfer.php”>
  <input type=”text” name=”toBankId”>
  <input type=”text” name=”money”>
  <? gen_input(); ?>
  <input type=”submit” name=”submit” value=”Submit”>
  </FORM>
  5).服务端核对令牌:
  这个很简单,这里不再?嗦了。
  上面这个其实不完全符合“并行会话的兼容”的规则,大家可以在此基础上修改。