当前位置:首页 > PHP教程 > php高级应用 > 列表

深入分析php表单加入Token防止重复提交的例子

发布:smiling 来源: PHP粉丝网  添加日期:2018-05-31 10:25:58 浏览: 评论:0 

Token浅谈:Token,就是令牌,最大的特点就是随机性,不可预测。一般黑客或软件无法猜测出来。

那么,Token有什么作用?又是什么原理呢?

Token一般用在两个地方——防止表单重复提交、anti csrf攻击(跨站点请求伪造)。

两者在原理上都是通过session token来实现的。当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。

然后,如果应用于“anti csrf攻击”,则服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。

不过,如果应用于“防止表单重复提交”,服务器端第一次验证相同过后,会将涩session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变了。

上面的session应用相对安全,但也叫繁琐,同时当多页面多请求时,必须采用多Token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可用cookie存储验证信息的方法来代替session Token。比如,应对“重复提交”时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。

不过,cookie存储有个致命弱点,如果cookie被劫持(xss攻击很容易得到用户cookie),那么又一次gameover。黑客将直接实现csrf攻击。

深入分析php表单加入Token防止重复提交的例子,所以,安全和高效相对的。具体问题具体对待吧。

php表单加入Token防止重复提交:原理在于生成一个随机字符串放在session里,提交表单后来验证这个字符串,可以做到防止他人自己写form来欺骗提交,重复提交或者双击提交。

深入分析php表单加入Token防止重复提交的例子,简单的用php实现的代码如下:

  1. <?php 
  2. /* 
  3. * PHP简单利用token防止表单重复提交 
  4. * 此处理方法纯粹是为了给初学者参考 
  5. */ 
  6. session_start(); 
  7. function set_token() { 
  8.   $_SESSION['token'] = md5(microtime(true)); 
  9. } 
  10. function valid_token() { 
  11.   $return = $_REQUEST['token'] === $_SESSION['token'] ? true : false; 
  12.   set_token(); 
  13.   return $return; 
  14. } 
  15. //如果token为空则生成一个token 
  16. if(!isset($_SESSION['token']) || $_SESSION['token']=='') { 
  17.   set_token(); 
  18. } 
  19. if(isset($_POST['test'])){ 
  20.   if(!valid_token()){ 
  21.     echo "token error"; 
  22.   }else{ 
  23.     echo '成功提交,Value:'.$_POST['test']; 
  24.   } //phpfensi.com 
  25. } 
  26. ?> 
  27. <form method="post" action=""> 
  28.   <input type="hidden" name="token" value="<?php echo $_SESSION['token']?>"> 
  29.   <input type="text" name="test" value="Default"> 
  30.   <input type="submit" value="提交" /> 
  31. </form> 

上面的比较简单一点的方法,下面的代码更加安全一点。

Token.php

  1. <?php 
  2. /* 
  3.  * Created on 2013-3-25 
  4.  * 
  5.  * To change the template for this generated file go to 
  6.  * Window - Preferences - PHPeclipse - PHP - Code Templates 
  7.  */ 
  8. function getToken($len = 32, $md5 = true) { 
  9.   # Seed random number generator 
  10.   # Only needed for PHP versions prior to 4.2 
  11.   mt_srand((double) microtime() * 1000000); 
  12.   # Array of characters, adjust as desired 
  13.   $chars = array ( 
  14.     'Q', 
  15.     '@', 
  16.     '8', 
  17.     'y', 
  18.     '%', 
  19.     '^', 
  20.     '5', 
  21.     'Z', 
  22.     '(', 
  23.     'G', 
  24.     '_', 
  25.     'O', 
  26.     '`', 
  27.     'S', 
  28.     '-', 
  29.     'N', 
  30.     '<', 
  31.     'D', 
  32.     '{', 
  33.     '}', 
  34.     '[', 
  35.     ']', 
  36.     'h', 
  37.     ';', 
  38.     'W', 
  39.     '.', 
  40.     '/', 
  41.     '|', 
  42.     ':', 
  43.     '1', 
  44.     'E', 
  45.     'L', 
  46.     '4', 
  47.     '&', 
  48.     '6', 
  49.     '7', 
  50.     '#', 
  51.     '9', 
  52.     'a', 
  53.     'A', 
  54.     'b', 
  55.     'B', 
  56.     '~', 
  57.     'C', 
  58.     'd', 
  59.     '>', 
  60.     'e', 
  61.     '2', 
  62.     'f', 
  63.     'P', 
  64.     'g', 
  65.     ')', 
  66.     '?', 
  67.     'H', 
  68.     'i', 
  69.     'X', 
  70.     'U', 
  71.     'J', 
  72.     'k', 
  73.     'r', 
  74.     'l', 
  75.     '3', 
  76.     't', 
  77.     'M', 
  78.     'n', 
  79.     '=', 
  80.     'o', 
  81.     '+', 
  82.     'p', 
  83.     'F', 
  84.     'q', 
  85.     '!', 
  86.     'K', 
  87.     'R', 
  88.     's', 
  89.     'c', 
  90.     'm', 
  91.     'T', 
  92.     'v', 
  93.     'j', 
  94.     'u', 
  95.     'V', 
  96.     'w', 
  97.     ',', 
  98.     'x', 
  99.     'I', 
  100.     '$', 
  101.     'Y', 
  102.     'z', 
  103.     '*' 
  104.   ); 
  105.   # Array indice friendly number of chars; 
  106.   $numChars = count($chars) - 1; 
  107.   $token = ''; 
  108.   # Create random token at the specified length 
  109.   for ($i = 0; $i < $len; $i++) 
  110.     $token .= $chars[mt_rand(0, $numChars)]; 
  111.   # Should token be run through md5? 
  112.   if ($md5) { 
  113.     # Number of 32 char chunks 
  114.     $chunks = ceil(strlen($token) / 32); 
  115.     $md5token = ''; 
  116.     # Run each chunk through md5 
  117.     for ($i = 1; $i <= $chunks; $i++) 
  118.       $md5token .= md5(substr($token, $i * 32 - 32, 32)); 
  119.     # Trim the token 
  120.     $token = substr($md5token, 0, $len); 
  121.   } 
  122.   return $token; 
  123. } 
  124. ?> 

form.php

  1. <?php 
  2. include_once("token.php"); 
  3. $token = getToken(); 
  4. session_start(); 
  5. $_SESSION['token'] = $token; 
  6. ?> 
  7. <form action="action.php" method="post" 
  8. <input type="hidden" name="token" value="<?=$token?>" /> 
  9. <!-- 其他input submit之类的 --> 
  10. </form> 

action.php

  1. <?php 
  2. session_start(); 
  3. if($_POST['token'] == $_SESSION['token']){ 
  4.   unset($_SESSION['token']); 
  5.   echo "这是一个正常的提交请求"; 
  6. }else{ 
  7.   echo "这是一个非法的提交请求"; 
  8. } 
  9. ?> 

Tags: 表单 例子 Token

分享到: