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

 更新时间:2016年11月25日 17:17  点击:1920
下面我们来看一篇关于深入分析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 "这是一个非法的提交请求";
}
?>

php模拟reffer破解防止盗用图片,这个就是告诉对方我是正常来访问的哦,下面我们一起来看看如何实现吧。

当我们需要调用其他网站图片的时候,其他网站的图片往往显示一个不显示,但是单独放在浏览器访问,却又可以。

php

模拟reffer破解防止盗用图片

<?php
error_reporting(0);
 
$HOST = "java-er.com";
 
 
require 'class/db.php';
header("Content-type:   image/png");
 
$id = $_GET["id"];
$sql = "select * from blog where id=$id";
$row = $db->queryRow($sql);
$url = $row["url"];
//读出来的URL为http://www.sina.com.cn/aaad.html 一会充当reffer
 
$imgurl = $_GET["url"];
 
//提取图片domain
$domain = preg_replace("/^http:\/\/(.+?)\/.+?$/","$1",$imgurl);
 
//兼容原来的网站 比如/2.jpg
if($url==""){
    $url = $imgurl;
}
 
if(!preg_match("/^http:\/\/.*?$/", $imgurl)){
    $domain = $HOST;
    $imgurl = "http://".$HOST."/".$imgurl;
    $url = $imgurl;
}
 
 
//兼容原来的网站 END
 
 
 
 
//image.58.com/showphone.aspx?t=v55&v=0926DC20FE0C323BH29559C838D7CB65E
 
$fp = fsockopen("$domain", 80, $errno, $errstr, 30);   
if (!$fp) {   
    echo "ERR:$errstr ($errno)<br />\n";
} else {   
  $out = "GET $imgurl HTTP/1.1\r\n";   
  //$out = "GET / HTTP/1.1\r\n";   
    $out .= "Accept:*/*\r\n";   
    $out .= "Host: $domain\r\n";   
    $out .= "Referer: $url\r\n";   
    $out .= "Connection: Close\r\n\r\n";   
  $str = "";
    fwrite($fp, $out);
    while (!feof($fp)) {   
        $str.=fgets($fp, 128);   
    }   
  $str = trimHeader($str);
  echo $str;
    fclose($fp);   
}  
 
 
function   trimHeader($content){
        $array=split("\r\n\r\n",$content);
        return   $array[1];
}
 
?>
//自己网页输入图片内容的时候自动替换

$c = preg_replace("/<img src=\"(.+?)\".*?>/is","<img src=\"/showimg_article.php?id=$id&url=$1\" />",$c);
如果你是一名技术人员可加我QQ 2651-0442-02,如果你是java技术人还可以加入QQ群 1784-9136-0

首发地址:月小升博客 –

重复数组在工作中就和重复数据一样可能影响到统计了,这里我们来看在php中重复数组的一个处理操作步骤。


php本身有提供一些函数,有一个出去重复的函数就是array_unique,这个函数会去除相同的值,这样可以给我们开发者带来方便,去除重复的值后在获取数组的长度,和未去除重复的长度来比较,下面代码不只是否可以用在二维数组上,我用的是一维数组
 
php 判断是否有重复数组代码

  if(count($pf_shuliang) != count(array_unique($pf_shuliang))) showErr("批发数量不可重复",$ajax);
 

二维数组根据键值排序

public function sort($arr,$sort,$v){    //$arr->数组   $sort->排序顺序标志   $value->排序字段
 
    if($sort == "0"){                   //排序顺序标志 SORT_DESC 降序;SORT_ASC 升序 
            $sort = "SORT_ASC";
    }elseif ($sort == "1") {
            $sort = "SORT_DESC";
    }
     
    foreach($arr as $uniqid => $row){ 
        foreach($row as $key=>$value){                    
                $arrsort[$key][$uniqid] = $value;
            } 
        } 
        if($sort){
        array_multisort($arrsort[$v], constant($sort), $arr); 
    }      
     return $arr;
}

方法三

<?php     
$input = array(4, "4", "3", 4, 3, "3");     
$result = array_unique($input);     
var_dump($result);     
?>

第一个单元将被保留

例子1. array_unique() 例子

<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);?>上例将输出:


Array([a] => green[0] => red[1] => blue)例子2. array_unique() 和类型
上例将输出:

<?php
$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);?>

二维数组排序与普通数据排序不一样因为二维数组排序需要使用一些一维数据用不到的方式,具体的我们来看二维数组排序的例子。


昨天要排序数组的时候发现了,要按时间排序,但是php并没有内设这个函数,所以在网上找到了这个代码,第一个参数为数组,第二个是要排序的元素,第三个为排序方式,
 
下面就是php 二维数组排序的代码

function arraySort($arr, $keys, $type = 'asc') {
         $keysvalue = $new_array = array();
         foreach ($arr as $k => $v){
             $keysvalue[$k] = $v[$keys];
         }
         $type == 'asc' ? asort($keysvalue) : arsort($keysvalue);
         reset($keysvalue);
         foreach ($keysvalue as $k => $v) {
            $new_array[$k] = $arr[$k];
         }
         return $new_array;
     }

$arr[] = array("name"=>"1","time"=>1) ;

array_multisort(array1,sorting order, sorting type,array2,array3..)是对多个数组或多维数组进行排序的函数。

<?php 
 
    function my_sort($arrays,$sort_key,$sort_order=SORT_ASC,$sort_type=SORT_NUMERIC ){  
        if(is_array($arrays)){  
            foreach ($arrays as $array){  
                if(is_array($array)){  
                    $key_arrays[] = $array[$sort_key];  
                }else{  
                    return false;  
                }  
            }  
        }else{  
            return false;  
        } 
        array_multisort($key_arrays,$sort_order,$sort_type,$arrays);  
        return $arrays;  
    } 
 
    $person =  array( 
                    array('id'=>1,'name'=>'fj','weight'=>100,'height'=>180), 
                    array('id'=>2,'name'=>'tom','weight'=>53,'height'=>150), 
                    array('id'=>3,'name'=>'jerry','weight'=>120,'height'=>156), 
                    array('id'=>4,'name'=>'bill','weight'=>110,'height'=>190), 
                    array('id'=>5,'name'=>'linken','weight'=>80,'height'=>200), 
                    array('id'=>6,'name'=>'madana','weight'=>95,'height'=>110), 
                    array('id'=>7,'name'=>'jordan','weight'=>70,'height'=>170) 
                ); 
     
    var_dump($person); 
     
    $person = my_sort($person,'name',SORT_ASC,SORT_STRING); 
 
    var_dump($person); 
     
    $person = my_sort($person,'weight'); 
 
    var_dump($person); 
?> 

结果如下:
 array (size=7)
  0 =>
    array (size=4)
      'id' => int 1
      'name' => string 'fj' (length=2)
      'weight' => int 100
      'height' => int 180
  1 =>
    array (size=4)
      'id' => int 2
      'name' => string 'tom' (length=3)
      'weight' => int 53
      'height' => int 150
  2 =>
    array (size=4)
      'id' => int 3
      'name' => string 'jerry' (length=5)
      'weight' => int 120
      'height' => int 156
  3 =>
    array (size=4)
      'id' => int 4
      'name' => string 'bill' (length=4)
      'weight' => int 110
      'height' => int 190
  4 =>
    array (size=4)
      'id' => int 5
      'name' => string 'linken' (length=6)
      'weight' => int 80
      'height' => int 200
  5 =>
    array (size=4)
      'id' => int 6
      'name' => string 'madana' (length=6)
      'weight' => int 95
      'height' => int 110
  6 =>
    array (size=4)
      'id' => int 7
      'name' => string 'jordan' (length=6)
      'weight' => int 70
      'height' => int 170
array (size=7)
  0 =>
    array (size=4)
      'id' => int 4
      'name' => string 'bill' (length=4)
      'weight' => int 110
      'height' => int 190
  1 =>
    array (size=4)
      'id' => int 1
      'name' => string 'fj' (length=2)
      'weight' => int 100
      'height' => int 180
  2 =>
    array (size=4)
      'id' => int 3
      'name' => string 'jerry' (length=5)
      'weight' => int 120
      'height' => int 156
  3 =>
    array (size=4)
      'id' => int 7
      'name' => string 'jordan' (length=6)
      'weight' => int 70
      'height' => int 170
  4 =>
    array (size=4)
      'id' => int 5
      'name' => string 'linken' (length=6)
      'weight' => int 80
      'height' => int 200
  5 =>
    array (size=4)
      'id' => int 6
      'name' => string 'madana' (length=6)
      'weight' => int 95
      'height' => int 110
  6 =>
    array (size=4)
      'id' => int 2
      'name' => string 'tom' (length=3)
      'weight' => int 53
      'height' => int 150
array (size=7)
  0 =>
    array (size=4)
      'id' => int 2
      'name' => string 'tom' (length=3)
      'weight' => int 53
      'height' => int 150
  1 =>
    array (size=4)
      'id' => int 7
      'name' => string 'jordan' (length=6)
      'weight' => int 70
      'height' => int 170
  2 =>
    array (size=4)
      'id' => int 5
      'name' => string 'linken' (length=6)
      'weight' => int 80
      'height' => int 200
  3 =>
    array (size=4)
      'id' => int 6
      'name' => string 'madana' (length=6)
      'weight' => int 95
      'height' => int 110
  4 =>
    array (size=4)
      'id' => int 1
      'name' => string 'fj' (length=2)
      'weight' => int 100
      'height' => int 180
  5 =>
    array (size=4)
      'id' => int 4
      'name' => string 'bill' (length=4)
      'weight' => int 110
      'height' => int 190
  6 =>
    array (size=4)
      'id' => int 3
      'name' => string 'jerry' (length=5)
      'weight' => int 120
      'height' => int 156

这里的重点就是,先把要排序的key存到一个一维数组中,然后就可以使用array_multisort()这个函数,将数组按照key进行排序了,当然,这里的排序你完全可以不适用array_multisort()这个函数,仅仅通过foreach遍历也能达到这个效果,但是既然php开发者给我们提供了更好的办法,我们就可以省去不必要的麻烦了

[!--infotagslink--]

相关文章

  • Linux下PHP安装curl扩展支持https例子

    安装curl扩展支持https是非常的重要现在许多的网站都使用了https了,下面我们来看一篇关于PHP安装curl扩展支持https例子吧。 问题: 线上运行的lamp服务器,默认yu...2016-11-25
  • sqlserver删除重复记录并且要保留一条记录

    删除重复数据,只保留一条用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢...2018-09-10
  • php使用floor去掉小数点的例子

    floor会产生小数了如果我们不希望有小数我们是可以去除小数点的了,下面一聚教程小编来为各位介绍php使用floor去掉小数点的例子,希望对各位有帮助。 float floor (...2016-11-25
  • C#删除字符串中重复字符的方法

    这篇文章主要介绍了C#删除字符串中重复字符的方法,涉及C#针对字符串的遍历及移除等操作的技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • postgresql 删除重复数据的几种方法小结

    这篇文章主要介绍了postgresql 删除重复数据的几种方法小结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-05
  • C#实现生成所有不重复的组合功能示例

    这篇文章主要介绍了C#实现生成所有不重复的组合功能,涉及C#数学运算中组合数运算的相关原理应用操作技巧,需要的朋友可以参考下...2020-06-25
  • 纯Css实现下拉菜单的简单例子

    下面我们来看一篇关于纯Css实现下拉菜单的简单例子,希望这篇文章能够给各位同学带来帮助,具体步骤如下. 大家可能会经常用到hover这属性,用hover实现鼠标经过的颜...2017-01-22
  • php时间日期对比与日期加减例子

    在php中日期对比用得比较多了,还有一个日期加减也用到不少,下面我拿两个例子来给大家介绍在php中日期操作方法吧,希望文章能给你带来帮助 功能需求 文章发布时段操...2016-11-25
  • php更新修改excel中的内容例子

    本例子不是读取Excel或生成新的Excel,而是读取现有的Excel文件,然后修改Excel中的数据,就像修改mysql中数据一样的哦。 代码如下 ...2016-11-25
  • php正则获取文章内容中图片地址例子

    正则提取图片中的地址我们介绍过很多的相关文章了,下面再来给各位介绍一个可以提取内容中第一张图片的例子,希望对各位有帮助。 代码如下 复制代码 ...2016-11-25
  • php获取QQ头像并显示的例子

    最近看到博客留言的头像有点别扭,因为游客的头像都是同一个头像,看着不是很舒服。虽然现在绝大多数的主题集成了Gavatar头像功能,先不说gavatar被墙的问题,我自己现在都没...2016-11-25
  • C#短时间内产生大量不重复的随机数

    在C#编程中,经常会碰到产生随机数的情况,并且是在短时间内产生一组随机数。如果这组随机数中有大量重复的,则达不到我们的要求...2020-06-25
  • PHP中如何防止外部恶意提交调用ajax接口

    本文简单介绍如何防止外部恶意调用ajax接口,以达到节省流量,减轻服务器压力的目的。...2016-04-15
  • php判断字符串是否包含另一个字符串例子

    php判断字符串是否包含另一个字符串的实现方法有许多的办法,像我们在网上一搜索可看到大量关于字符是否包含指定字符的方法,下面我把这些实用的例子整理一起与大家分享...2016-11-25
  • PHP date函数获取时间几个例子

    date函数是php中一个非常好用的日期获取函数了,我们可以使用它来获取指定日期或者当前日期了,下面我来简单的介绍一下date函数用法与常用用法吧。 PHP星期几获取代...2016-11-25
  • php中防止post提交重复数据

    重复提交数据我们在应用中经常会碰到了,今天我给各位介绍利用session来防止用户不小心重复提交数据的一个例子 原理非常的简单:就是用session在表单页面记录下,...2016-11-25
  • 用C#生成不重复的随机数的代码

    我们在做能自动生成试卷的考试系统时,常常需要随机生成一组不重复的题目,在.net Framework中提供了一个专门用来产生随机数的类System.Random...2020-06-25
  • 横向重复区域显示二法

    方法一. 注重这里有一个预先定义的图片记录集rsmpic 要横向重复的就是图片,请根据你的情况改为你的记录集名称.整洁地将横向重复内容放在一个表格内 <table width=...2016-11-25
  • 利用asp.net实现生成不重复订单号

    订单号在购物过程中起到了很好的识别作用,更方便的有利于工作人员识别商品,本文介绍利用asp.net实现生成订单号...2021-09-22
  • 帝国CMS同时发布到以下栏目避免重复调用的方法

    帝国CMS发布信息时有个 发布到以下栏目 的功能,非常棒。但是会导致列表页及其它地方调用时信息重复,解决办法如下http://bbs.phome.net/ShowThread/?threadid=338805&forumid=...2016-06-09