zoukankan      html  css  js  c++  java
  • php表单加入Token防止重复提交的方法分析

    http://www.jb51.net/article/94395.htm

    这篇文章主要介绍了php表单加入Token防止重复提交的方法,结合实例形式分析了Token防止重复提交的原理与使用技巧,需要的朋友可以参考下

    本文实例讲述了php表单加入Token防止重复提交的方法。分享给大家供大家参考,具体如下:

     

    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防止重复提交

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

    简单的用php实现的代码如下:

     
    <?php
    /*
    * PHP简单利用token防止表单重复提交
    * 此处理方法纯粹是为了给初学者参考
    */
    session_start();
    function set_token() {
       $_SESSION [ 'token' ] = md5(microtime(true));
    }
    function valid_token() {
       $return = $_REQUEST [ 'token' ] === $_SESSION [ 'token' ] ? true : false;
       set_token();
       return $return ;
    }
    //如果token为空则生成一个token
    if (!isset( $_SESSION [ 'token' ]) || $_SESSION [ 'token' ]== '' ) {
       set_token();
    }
    if (isset( $_POST [ 'test' ])){
       if (!valid_token()){
         echo "token error" ;
       } else {
         echo '成功提交,Value:' . $_POST [ 'test' ];
       }
    }
    ?>
    <form method= "post" action= "" >
       <input type= "hidden" name= "token" value= "<?php echo $_SESSION['token']?>" >
       <input type= "text" name= "test" value= "Default" >
       <input type= "submit" value= "提交" />
    </form>

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

    Token.php

     
    <?php
    /*
      * Created on 2013-3-25
      *
      * To change the template for this generated file go to
      * Window - Preferences - PHPeclipse - PHP - Code Templates
      */
    function getToken( $len = 32, $md5 = true) {
       # Seed random number generator
       # Only needed for PHP versions prior to 4.2
       mt_srand((double) microtime() * 1000000);
       # Array of characters, adjust as desired
       $chars = array (
         'Q' ,
         '@' ,
         '8' ,
         'y' ,
         '%' ,
         '^' ,
         '5' ,
         'Z' ,
         '(' ,
         'G' ,
         '_' ,
         'O' ,
         '`' ,
         'S' ,
         '-' ,
         'N' ,
         '<' ,
         'D' ,
         '{' ,
         '}' ,
         '[' ,
         ']' ,
         'h' ,
         ';' ,
         'W' ,
         '.' ,
         '/' ,
         '|' ,
         ':' ,
         '1' ,
         'E' ,
         'L' ,
         '4' ,
         '&' ,
         '6' ,
         '7' ,
         '#' ,
         '9' ,
         'a' ,
         'A' ,
         'b' ,
         'B' ,
         '~' ,
         'C' ,
         'd' ,
         '>' ,
         'e' ,
         '2' ,
         'f' ,
         'P' ,
         'g' ,
         ')' ,
         '?' ,
         'H' ,
         'i' ,
         'X' ,
         'U' ,
         'J' ,
         'k' ,
         'r' ,
         'l' ,
         '3' ,
         't' ,
         'M' ,
         'n' ,
         '=' ,
         'o' ,
         '+' ,
         'p' ,
         'F' ,
         'q' ,
         '!' ,
         'K' ,
         'R' ,
         's' ,
         'c' ,
         'm' ,
         'T' ,
         'v' ,
         'j' ,
         'u' ,
         'V' ,
         'w' ,
         ',' ,
         'x' ,
         'I' ,
         '$' ,
         'Y' ,
         'z' ,
         '*'
       );
       # Array indice friendly number of chars;
       $numChars = count ( $chars ) - 1;
       $token = '' ;
       # Create random token at the specified length
       for ( $i = 0; $i < $len ; $i ++)
         $token .= $chars [mt_rand(0, $numChars )];
       # Should token be run through md5?
       if ( $md5 ) {
         # Number of 32 char chunks
         $chunks = ceil ( strlen ( $token ) / 32);
         $md5token = '' ;
         # Run each chunk through md5
         for ( $i = 1; $i <= $chunks ; $i ++)
           $md5token .= md5( substr ( $token , $i * 32 - 32, 32));
         # Trim the token
         $token = substr ( $md5token , 0, $len );
       }
       return $token ;
    }
    ?>

    form.php

     
    <?php
    include_once ( "token.php" );
    $token = getToken();
    session_start();
    $_SESSION [ 'token' ] = $token ;
    ?>
    <form action= "action.php" method= "post"
    <input type= "hidden" name= "token" value= "<?=$token?>" />
    <!-- 其他input submit之类的 -->
    </form>

    action.php

     
    <?php
    session_start();
    if ( $_POST [ 'token' ] == $_SESSION [ 'token' ]){
       unset( $_SESSION [ 'token' ]);
       echo "这是一个正常的提交请求" ;
    } else {
       echo "这是一个非法的提交请求" ;
    }
    ?>
  • 相关阅读:
    Exercice_3.8
    Exercice_3.13.1_练习使用vector2
    Exercice_3.13_练习使用vetor
    Exercice_3.10_去掉string对象中的标点符号
    Exercice_3.7_判断两个字符串的大小和长度
    1-日期时间视图 2-长按事件
    View(视图)2
    View(视图)
    计算器(UI事件)给按钮添加监听器
    Activity(活动)
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15454478.html
Copyright © 2011-2022 走看看