PHP防止重复提交表单的例子

 更新时间:2016年11月25日 15:34  点击:1626
防止重复提交表单的方法小编介绍过的不知道有多案了,如数据库判断,js验证,cookies验证及session验证,下面一起来看一个例子。

我们提交表单的时候,不能忽视的一个限制是防止用户重复提交表单,因为有可能用户连续点击了提交按钮或者是攻击者恶意提交数据,那么我们在提交数据后的处理如修改或添加数据到数据库时就会惹上麻烦。


那么如何规避这中重复提交表单的现象出现呢?我们可以从很多方面入手,首先从前端做限制。前端JavaScript在按钮被点击一次后禁用,即disabled,这个方法简单的防止了多次点击提交按钮,但是缺点是如果用户禁用了javascript脚本则失效。第二,我们可以在提交后做redirect页面重定向,即提交后跳转到新的页面,主要避免F5重复提交,但是也有不足之处。第三,就是数据库做唯一索引约束。第四,就是做session令牌验证。

我们现在来了解下简单的利用session token来防止表单重复提交的方法。
我们在表单中加一个input隐藏域,即type="hidden",其value值用来保存token值,当页面刷新的时候这个token值会变化,提交后判断token值是否正确,如果前台提交的token与后台不匹配,则认为是重复提交。

 代码如下 复制代码
<?php
/*
* PHP简单利用token防止表单重复提交
*/
session_start();
header("Content-Type: text/html;charset=utf-8");
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['web'])){
    if(!valid_token()){
        echo "token error,请不要重复提交!";
    }else{
        echo '成功提交,Value:'.$_POST['web'];
    }
}else{
?>
    <form method="post" action="">  
        <input type="hidden" name="token" value="<?php echo $_SESSION['token']?>">  
        <input type="text" class="input" name="web" value="www,111cn.net">  
        <input type="submit" class="btn" value="提交" />  
    </form>
<?php    
}
?>

以上是一个简单的防止重复提交表单的例子,仅供参考。那么实际项目开发中,会对表单token做更复杂的处理,即我们说的令牌验证。可能要做的处理有:验证来源域,即来路,是否为外部提交;匹配要执行的动作,是添加、修改or删除;其次最重要的是构建token,token可以采用可逆的加密算法,尽可能复杂,因为明文还是不安全的。令牌验证的具体算法可以参考各大PHP框架,如ThinkPHP提供了很好的令牌验证功能。

函数引用与php中变量引用一样使用的是&符号了,今天我们就一起来看看函数的引用返回的一些例子,希望这些例子能够对各位有帮助.

引用返回

手册里是这么写的:引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!要返回引用

当你想将函数的返回引用绑定到某个变量时,PHP允许你这么做:

function &returns_reference()
{
    static $someref = 0;
    $someref++;
    return $someref;
}
 
$newref = &returns_reference();//引用返回,相当于 $newref = &$someref;
echo $newref; //1
 
$notref = returns_reference(); //值传递的是副本
$newref = 100;
echo $notref; //2
 
$newref = 100;
echo returns_reference(); //101

可见,想让函数返回引用,必须在函数申明和赋值时都带上&操作符。
对于类中方法也是如此:

class foo {
    public $value = 0;
 
    public function &getValue() {
        return $this->value;
    }
}
 
$obj = new foo;
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;


一些简单的例子

看下面的简单例子,尝试去理解引用返回。

<?php

function &test()
{
 // 声明一个静态变量
    static $b = 0;

    $b = $b+1;
    echo $b;
    return $b;
}

$a = test(); //这条语句会输出 $b 的值为 1

$a = 5;
$a = test(); //这条语句会输出 $b 的值为2

$a = &test(); //这条语句会输出 $b 的值为3

$a = 5;
$a = test(); //这条语句会输出 $b的值 为6

?>
程序运行结果:

1
2
3
6

尽管函数声明方式是 function &test() 这样,但我们通过这种方式 $a = test() 的函数调用得到的其实不是函数的引用返回,这跟普通的函数调用没有区别。PHP 规定通过 $a = &test() 这种方式得到的才是函数的引用返回。
用上面的例子来解释就是,$a = test() 这种方式调用函数,只是将函数的值赋给 $a 而已,而$a做任何改变都不会影响到函数中的$b。

而通过 $a = &test() 方式调用函数呢,它的作用是将 return $b 中的 $b 变量的内存地址与 $a 变量的内存地址指向了同一个地方。即产生了相当于这样的效果 ($a=&$b), 所以改变 $a 的值也同时改变了 $b 的值。所以在执行了

$a = &test();
$a = 5;
以后,$b的值变为了5。

再来个程序例子加深理解:

<?php
/*
** 值传递和引用传递,值传递传递的是值的一个复本,引用传递传递的是值指向的内存地址
*/

// 函数的引用,定义时也要加上 &
function &func($a,$b){  
 // 这里为了更直观看到效果,定义一个静态变量
 static $result = 0;   
 $result+=$a+$b;
 echo $result.'<br />';
 return $result;
}
 
$a = $b = 10;

// PHP里这样写函数的引用调用,和调用普通函数没有区别(只是将函数的返回值复制给$c这个变量,$c做任何改变不会影响上面函数中的$result)
// 要记住:PHP里的函数引用定义及调用都要在函数名前加上 &
$c = func($a,$b);
// 第一次执行func(),其静态变量$result的值变为 20(10+10)

// 改变$c的值,不会对下面一行语句产生影响
$c = 666; 
// 第二次执行func(),其静态变量$result的值变为 40(20+10+10)
$c = func($a,$b);

echo '<hr />';

// 这样才是PHP中引用函数的调用方式
$d = &func($a,$b); 
// 第三次执行func(),其静态变量$result的值变为 40(40+10+10)
$d = 888;
// 第四次执行func(),其静态变量$result的值变为 908(888+10+10)
$d = func($a,$b);

?>

 

生成IP我们只要生成一个字符串就可以了,在指定范围的int可存储的空间中就可以生成ipv4的ip数据了,下面我们一起来来看看.

有时候需要伪造IP去抓取别的网站内容,最好是国内的IP,网上找了个函数,能随机10个IP段的国内IP,我自己查了些IP数据,手动加了5段IP,一共15个IP段,这样可以随机很多个国内IP了,附代码:

function rand_ip(){
 $ip_long = array(
  array('607649792', '608174079'), //36.56.0.0-36.63.255.255
  array('975044608', '977272831'), //58.30.0.0-58.63.255.255
  array('999751680', '999784447'), //59.151.0.0-59.151.127.255
  array('1019346944', '1019478015'), //60.194.0.0-60.195.255.255
  array('1038614528', '1039007743'), //61.232.0.0-61.237.255.255
  array('1783627776', '1784676351'), //106.80.0.0-106.95.255.255
  array('1947009024', '1947074559'), //116.13.0.0-116.13.255.255
  array('1987051520', '1988034559'), //118.112.0.0-118.126.255.255
  array('2035023872', '2035154943'), //121.76.0.0-121.77.255.255
  array('2078801920', '2079064063'), //123.232.0.0-123.235.255.255
  array('-1950089216', '-1948778497'), //139.196.0.0-139.215.255.255
  array('-1425539072', '-1425014785'), //171.8.0.0-171.15.255.255
  array('-1236271104', '-1235419137'), //182.80.0.0-182.92.255.255
  array('-770113536', '-768606209'), //210.25.0.0-210.47.255.255
  array('-569376768', '-564133889'), //222.16.0.0-222.95.255.255
 );
 $rand_key = mt_rand(0, 14);
 $huoduan_ip= long2ip(mt_rand($ip_long[$rand_key][0], $ip_long[$rand_key][1]));
 return $huoduan_ip;
}

补充:long2ip函数

把存储空间降到了接近四分之一(char(15)的15个字节对整形的4个字节),计算一个特定的地址是不是在一个区段内页更简单了,而且加快了搜索和排序的速度(虽然有时仅仅是快了一点)。

例子

$ip = long2ip(3232235881);  
echo $ip;//127.255.255.255

下面我们一起来看一篇关于SAE 上安装 Wecenter 错误问题处理例子,希望这篇文章能够帮助到各位朋友。

今天其实想搭建个社区,专门为 Zephir/Phalcon/Yaf/Docker/Swoole 建设一个社区, 专门为 C 语言的PHP框架和 C 语言扩展做一个,刚开始挺高兴的,直接用 wecenter 搭建多好,而且官网说支持 SAE,我就信心满满的去了,结果不行,坑爹呀,新浪那么大字,mysql 不支持 host:port 没看吗? 稍微修改一下就可以了。
0x01

修改 system\Zend\Db\Adapter\Mysqli.php ,搜索找到 // Suppress connection warnings here. ,然后在上边加入以下代码:

  

 代码如下 复制代码
  //修复SAE上连接错误 BUG add by widuu 2015/4/23
    if (defined('IN_SAE')){
        $host = $this->_config['host'];
        $this->_config['host'] = strstr($host,':',true);
        $port = trim(strstr($host,':'),':');
    }
    // end by widuu

修改 system\Zend\Db\Adapter\Pdo\Abstract.php,搜索一下代码:

 代码如下 复制代码
return $this->_pdoType . ':' . implode(';', $dsn);

然后替换成如下这样:

 代码如下 复制代码

//修复SAE上连接错误 BUG add by widuu 2015/4/23
if (defined('IN_SAE')){
     $host = $dsn['host'];
     $dsn['host'] = strstr($host,':',true);
     $dsn['port'] = 'port='.trim(strstr($host,':'),':');
}
// end by widuu
return $this->_pdoType . ':' . implode(';', $dsn);
0x02

伪静态不管用,大哥你知道吗,最好看看官方的 API,然后伪静态变成如下就可以了:

name: 你的应用名称
version: 你的版本
handle:

 代码如下 复制代码
- rewrite: if (!-d && !-f) goto "/index.php?%{QUERY_STRING}"

好就到这里,明天预告,更新 Phalcon 的东西,我也想更新 YAF 的知识,当然一个一个慢慢来。然后是 Zephir。

股票信息查询功能我们是需要抓取第三方的数据,然后我们再把这些数据进行分析组成自己想要的,下面我们来看一个php 股票信息查询类。

今天一个二逼朋友让我帮忙写个股票查询的类,来集成到微信中,所以花了一点时间写了一个不完整的,哈哈,如果有想玩的人,可以继续提交代码,让它变得完善起来!!
GitHub 地址:github.com/widuu/stock

代码如下:

 代码如下 复制代码

class stock{

    /**
     * 股票数据接口
     */

    const STOCK_URL = "http://apis.baidu.com/apistore/stockservice/stock";
   
    /**
     * 通过拼音或者汉字获取股票代码
     */

    const SOCKET_SUGGEST = "http://cjhq.baidu.com/suggest?code5=";

    /**
     * 单态实例
     */

    private static $instance;

    /**
     * API 密钥
     */

    private static $apikey;

    /**
     * 实例化类和指定API KEY
     * @param  apikey  string
     * @return instance object
     */

    public static function getInstance($apikey){
       
        if( self::$instance == NULL ){
            self::$instance = new self;
            self::$apikey = $apikey;
        }

        return self::$instance;
    }

    /**
     * 获取股票名称
     * @param  stockid    string
     * @return stockName  string
     */

    public static function getName($stockid){
        $result = self::getSingleStock($stockid);
        return $result['name'];
    }

    /**
     * 获取最后更新时间
     * @param  stockid string
     * @return time    string
     */

    public static function getTime($stockid){
        $result = self::getSingleStock($stockid);
        return $result['date'].$result['time'];
    }

    /**
     * 获取K线图地址
     * @param  stockid  string
     * @param  date     string  min/day/week/mouth
     * @return imageUrl string
     */

    public static function getKline($stockid,$date='min'){
        $result = self::getSingleStock($stockid);
        return $result['klinegraph'][$date.'url'];
    }

    /**
     * 抓取整只股票的数据
     * @param  stockid  string
     * @return stock infomation array
     */

    public static function getSingleStock($stockid){
        $type = preg_match('/(\d+){6}/is', $stockid);
        if ( $type == 0 ){
            $stockid = self::getStockId($stockid);
        }
        $stock_url = self::STOCK_URL."?stockid=".$stockid;
        $result = self::httpGet( $stock_url , true );
        if( $result['errNum'] != 0 ){
            throw new Exception($result['errMsg'], 1);
            return;
        }
        return $result['retData'];
    }

    /**
     * 输入拼音或者汉字来获取股票代码
     * @param  name    string
     * @return stockid string
     */

    private static function getStockId($name){
        $result = self::httpGet( self::SOCKET_SUGGEST.urlencode(iconv('utf-8', 'GBK', $name)),false );
        if (empty($result)){
            throw new Exception("stock name not exists", 2);
            return;
        }
        $stockid = $result['Result'][0]['code'];
        $stock   = explode('.', $stockid);
        return   $stock[1].$stock[0];
    }

    /**
     * GET获取方法
     * @param  param string  参数
     * @author widuu
     */

    private static function httpGet($url,$header=false) {
        $curlHandle = curl_init();
        curl_setopt( $curlHandle , CURLOPT_URL, $url );
        if( $header ){
           curl_setopt( $curlHandle , CURLOPT_HTTPHEADER  , array('apikey:'.self::$apikey));
        }
        curl_setopt( $curlHandle , CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt( $curlHandle , CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt( $curlHandle , CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt( $curlHandle , CURLOPT_TIMEOUT, 10 );
        $content = curl_exec( $curlHandle );
        curl_close( $curlHandle );
        return $header ? json_decode($content,true) :json_decode(iconv('GBK','utf-8',trim($content)),true);
    }
}

//测试代码
stock::getInstance("5040bcbfebb0a4cffc7be278723255aa");
print_r(stock::getSingleStock('sh601000'));
echo stock::getKline('紫金矿业');

[!--infotagslink--]

相关文章

  • JS中artdialog弹出框控件之提交表单思路详解

    artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口。本文给大家介绍JS中artdialog弹出框控件之提交表单思路详解,对本文感兴趣的朋友一起学习吧...2016-04-19
  • 使用JQuery实现Ctrl+Enter提交表单的方法

    有时候我们为了省事就操作键盘组合键去代替使用鼠标,我们今天就使用JQuery实现Ctrl+Enter提交表单。我们发帖时,在内容输入框中输入完内容后,可以点击“提交”按钮来发表内容。可是,如果你够“懒”,你可以不用动鼠标,只需按...2015-10-23
  • sqlserver删除重复记录并且要保留一条记录

    删除重复数据,只保留一条用SQL语句,删除掉重复项只保留一条在几千条记录里,存在着些相同的记录,如何能用SQL语句,删除掉重复的呢...2018-09-10
  • vue项目,代码提交至码云,iconfont的用法说明

    这篇文章主要介绍了vue项目,代码提交至码云,iconfont的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-30
  • angularjs $http实现form表单提交示例

    这篇文章主要介绍了angularjs $http实现form表单提交示例,非常具有实用价值,需要的朋友可以参考下 ...2017-06-15
  • html表单提交中method请求Get和Post区别详解

    在html表单提交中method请求Get和Post区别其实很显示的,get提交会是url形式的并且数据量不能太多,而post数据是在浏览器url看不到的并且可以是大数据量而且get安全性非...2016-09-20
  • C#删除字符串中重复字符的方法

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

    这篇文章主要介绍了postgresql 删除重复数据的几种方法小结,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-02-05
  • 基于Postgresql 事务的提交与回滚解析

    这篇文章主要介绍了基于Postgresql 事务的提交与回滚解析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
  • C#实现生成所有不重复的组合功能示例

    这篇文章主要介绍了C#实现生成所有不重复的组合功能,涉及C#数学运算中组合数运算的相关原理应用操作技巧,需要的朋友可以参考下...2020-06-25
  • JQuery异步提交表单与文件上传功能示例

    这篇文章主要介绍了JQuery异步提交表单与文件上传功能,结合实例形式分析了jQuery表单提交及文件传输操作的相关实现技巧,需要的朋友可以参考下...2017-01-16
  • Ajax+FormData+javascript实现无刷新表单信息提交

    在前端开发中ajax,formdata和js实现无刷新表单信息提交非常棒,接下来通过本文给大家介绍Ajax+FormData+javascript实现无刷新表单信息提交的相关资料,需要的朋友可以参考下...2016-10-25
  • JavaScript中数组去除重复的三种方法

    本文通过三种方法给大家介绍js数组去除重复的方法,实用性非常高,感兴趣的朋友一起学习吧...2016-04-24
  • 设置表单提交数据的编码两种办法

    有时我们提交页面编码为gb2312但是接受的php页面的编码为uft8这样如果我们直接这样提交过去,肯定是出现乱码了,那么我们可以在提交表单时设置提交数据编码即可解决。...2016-09-20
  • JS中from 表单序列化提交的代码

    这篇文章主要介绍了javascript中from 表单序列化提交的实现方法,代码简单易懂,非常不错,需要的朋友参考下吧...2017-01-23
  • Jquery表单验证失败后不提交的解决方法

    很多人可能都会遇到在调试的时候用了return了false,可为什么还会提交呢?这个问题我最近也碰到了,尝试了多次也没有用,后来终于发现了其中的问题,下面分享处理给大家,让同样遇到这个问题的朋友们能够看看,有需要的朋友们下面来一起看看吧。...2016-10-20
  • SpringMVC表单提交参数400错误解决方案

    这篇文章主要介绍了SpringMVC表单提交参数400错误解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-10-21
  • C#短时间内产生大量不重复的随机数

    在C#编程中,经常会碰到产生随机数的情况,并且是在短时间内产生一组随机数。如果这组随机数中有大量重复的,则达不到我们的要求...2020-06-25
  • PHP表单提交数据之get,post实例详解

    本文章来给大家介绍一个入门教程关于PHP表单提交数据之get,post实例,有需要了解的同学可进入参考参考。 1.什么是表单 所谓表单,说简单点就是一对form标签。即:<form...2016-11-25
  • Javascript的表单验证-提交表单

    JavaScript 可用来在数据被送往服务器前对 HTML 表单中的这些输入数据进行验证。通过本文给大家介绍Javascript的表单验证-提交表单,对javascript表单验证,提交表单相关知识感兴趣的朋友一起学习吧...2016-03-22