php表单加入Token防止重复提交的方法分析


Posted in PHP onOctober 10, 2016

本文实例讲述了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防止重复提交的方法分析

所以,安全和高效相对的。具体问题具体对待吧。

php表单加入Token防止重复提交

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

php表单加入Token防止重复提交的方法分析

简单的用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程序设计有所帮助。

PHP 相关文章推荐
php is_file 判断给定文件名是否为一个正常的文件
May 10 PHP
php短域名转换为实际域名函数
Jan 17 PHP
fleaphp crud操作之findByField函数的使用方法
Apr 23 PHP
PDO版本问题 Invalid parameter number: no parameters were bound
Jan 06 PHP
Yii 快速,安全,专业的PHP框架
Sep 03 PHP
php魔术变量用法实例详解
Nov 13 PHP
CI配置多数据库访问的方法
Mar 28 PHP
thinkPHP框架对接支付宝即时到账接口回调操作示例
Nov 14 PHP
Thinkphp框架中D方法与M方法的区别
Dec 23 PHP
PHP根据树的前序遍历和中序遍历构造树并输出后序遍历的方法
Nov 10 PHP
php打开本地exe程序,js打开本地exe应用程序,并传递相关参数方法
Feb 06 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
Nov 21 PHP
Laravel5中防止XSS跨站攻击的方法
Oct 10 #PHP
php中让人头疼的浮点数运算分析
Oct 10 #PHP
Laravel实现自定义错误输出内容的方法
Oct 10 #PHP
PHP定时任务获取微信access_token的方法
Oct 10 #PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
Oct 10 #PHP
PHP简单数据库操作类实例【支持增删改查及链式操作】
Oct 10 #PHP
Ajax实现对静态页面的文章访问统计功能示例
Oct 10 #PHP
You might like
牡丹941资料
2021/03/01 无线电
PHP查询MySQL大量数据的时候内存占用分析
2011/07/22 PHP
详解WordPress中简码格式标签编写的基本方法
2015/12/22 PHP
总结对比php中的多种序列化
2016/08/28 PHP
利用PHP获取网站访客的所在地位置
2017/01/18 PHP
用javascript操作xml
2006/11/04 Javascript
点图片上一页下一页翻页效果
2008/07/09 Javascript
Jquery.Form 异步提交表单的简单实例
2014/03/03 Javascript
JavaScript DOM节点添加示例
2014/07/16 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
2015/11/24 Javascript
javascript实现保留两位小数的多种方法
2015/12/18 Javascript
JS实现登录页面记住密码和enter键登录方法推荐
2016/05/10 Javascript
把json格式的字符串转换成javascript对象或数组的方法总结
2016/11/03 Javascript
微信小程序中使元素占满整个屏幕高度实现方法
2016/12/14 Javascript
javascript实现简单的ajax封装示例
2016/12/28 Javascript
详解vue-cli + webpack 多页面实例应用
2017/04/25 Javascript
Vue.js学习记录之在元素与template中使用v-if指令实例
2017/06/27 Javascript
webpack 2.x配置reactjs基本开发环境详解
2017/08/08 Javascript
微信小程序功能之全屏滚动效果的实现代码
2018/11/22 Javascript
Vue.js的动态组件模板的实现
2018/11/26 Javascript
Vue+Django项目部署详解
2019/05/30 Javascript
Python入门及进阶笔记 Python 内置函数小结
2014/08/09 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
Python计算开方、立方、圆周率,精确到小数点后任意位的方法
2018/07/17 Python
python urllib爬虫模块使用解析
2019/09/05 Python
python selenium循环登陆网站的实现
2019/11/04 Python
基于Python获取城市近7天天气预报
2019/11/26 Python
彻底解决pip下载pytorch慢的问题方法
2021/03/01 Python
HTML5之HTML元素扩展(上)—新增加的元素及使用概述
2013/01/31 HTML / CSS
美国销售第一的智能手机和平板电脑保护壳:OtterBox
2017/12/21 全球购物
雅高酒店中国:Accorhotels.com China
2018/03/26 全球购物
一站式跨境收款解决方案:Payoneer(派安盈)
2018/09/06 全球购物
教师评职称工作总结2015
2015/04/20 职场文书
文化大革命观后感
2015/06/17 职场文书
熟背这些句子,让您的英语口语突飞猛进(135句)
2019/09/06 职场文书
JavaScript高级程序设计之变量与作用域
2021/11/17 Javascript