如何真正解决表单重复提交问题php代码
正如令牌本身代表着权限,操作权,身份标志等等,所以我能不能为我的表单加上这么 一个身份标志,在客户端每次请求这个表单的时候同时生成一个令牌其挂钩,在提交时再进行判断,正确则接收并处理表单。实现本质就是如此,而反映到具体实现上,就需要用到一种叫 session的东西。关于session的解析,参见wiki
简单的理解就是session也是一种令 牌的概念,所以你可能会很惊奇,“什么我已经使用了令牌?!”,是的,但是我们要实现的不仅仅是session而是在其基础上附加一些数据来实现我们想要的表单令牌。So let's do it!
session在php中也是被存放在$_SESSION这个超级全局变量里面的,启用起请使用session_start(),关于其他服务端脚本原理一样,只是可能调用方法名不一致而已。加入 token后的代码如下:
| 代码如下 | |
|
<?php //开启session session_start(); if ( isset( $_POST['submit'] ) && valid_token() ) { //表单 提交处理 } /** * 生成令牌 * @return string MD5加密后的时间戳 */ function create_token() { //当前时间戳 $timestamp = time(); $_SESSION['token'] = $timestamp; return md5( $timestamp ); } /** * 是否有效令牌 * @return bool */ function valid_token() { if ( isset( $_SESSION['token'] ) && isset( $_POST['token'] ) && $_POST['token'] == md5( $_SESSION['token'] ) ) { //若正确将本次令牌销毁掉 $_SESSION['token'] = ''; return true; } return false; } ?> <?php if ( isset( $state ) && $state ) { //数据插入成功 ?> <p>插入成功 <a href="form.php">返回 </a></p> <?php } else { //失败或者没有插入动作 ?> <form method="post"> <p> <label for="test">随便 输入点什么</label> <input type="text" name="data" id="test" /> </p> <p> <input type="submit" value="提 交" name="submit" /> </p> </ul> <!-- Token --> <input type="hidden" value="<?php echo create_token(); //生成 令牌 ?>" name="token" /> <!-- Token --> </form> <?php } ?> |
|
部分代码paperen这里省略,因为并不是重点,其实加的 东西只有3处:
第一,在表单结束前加入了一个input元素,记得type为hidden(隐藏域)
第二,增加了两个函数,create_token与valid_token,前者用来生成令牌 的后者用来验证令牌的
第三,在if中多加一个条件,valid_token
那就大功告成了,很简单,而且所有的东西都聚集在新加的两个函数中。paperen这里使用的令牌很 简单就是时间戳,将请求表单时的时间戳存储到$_SESSION['token']中,那么验证令牌就明白了,就是检查客户端提交过来的$_POST['token']是否与md5后的$_SESSION['token']一致 就行了,当然还要加上存在$_POST['token']与$_SESSION['token']这两个变量才行。
你可以将这个简单的令牌模式封装得更加棒并扩展一下功能,例如加上表单提交超时验证 也是个不错的动手机会。
最后附上之前paperen扩展codeingeter的Form_validation类文件,主要是扩展上令牌与表单超时。压缩包中welcome.php是控制器文件,请放置到 applicationcontroller中(如不想增加这个控制器可以打开然后将token方法复制下来放到已有的其他控制器中);MY_Form_validation.php请放到applicationlibraries中。
codeingeter的Form_validation类文件代码
| 代码如下 | |
|
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Welcome extends CI_Controller {
public function token()
//生成表单令牌
//form example |
|
form_validation_token
| 代码如下 | |
|
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
/**
/**
public function __construct()
/**
/**
/**
//提交的hash
if ( md5( $source_hash ) == $post_formhash )
/** |
|
【如何真正解决表单重复提交问题php代码】相关文章: