当前位置:首页 > 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. function valid_token() { 
  10.   $return = $_REQUEST['token'] === $_SESSION['token'] ? true : false; 
  11.   set_token(); 
  12.   return $return
  13. //如果token为空则生成一个token 
  14. if(!isset($_SESSION['token']) || $_SESSION['token']=='') { 
  15.   set_token(); 
  16. if(isset($_POST['test'])){ 
  17.   if(!valid_token()){ 
  18.     echo "token error"
  19.   }else
  20.     echo '成功提交,Value:'.$_POST['test']; 
  21.   } //phpfensi.com 
  22. ?> 
  23. <form method="post" action=""
  24.   <input type="hidden" name="token" value="<?php echo $_SESSION['token']?>"
  25.   <input type="text" name="test" value="Default"
  26.   <input type="submit" value="提交" /> 
  27. </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. ?> 

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. ?> 

Tags: 表单 例子 Token

分享到: