以前看过很多各种防止表单重复提交js或jquery程序,但这种只是一个简单的方法,如果我们不从这个页面提交表单,直接找到接受数据的页面这种js处理方法就无效了,下面我利用php一些方法来解决。
以前用的js表单防止重复提交方法
代码如下 | 复制代码 |
// 第一次提交 //重复提交 //以下三种方式分别调用 |
这样如果我直接做一个表单,然后提交给/test,上面代理就是一个摆设了,那我们要如何解决此问题
如果您已经知道如何解决的话那么这篇文章可能不适合你的口味,paperen这里也打算从基础开始讨论,所以希望一步看到解决方案的您也可能不太适合,所以请注意。So~开始吧 ~
paperen想您一定知道表单是什么吧,form元素就是表单,一般网页需要输入的地方必定使用了表单元素,也很常见,一般的代码如下:
代码如下 | 复制代码 |
method="post">
|
重点其实是form与input元素,p元素只是paperen私自加上去的,对后续的说明没有任何影响,其实很简单,所谓input就是输入了,你可以完全将input 元素理解为是用作用户输入,只是某些属性的(type)不能作为输入而已(这里就是submit),而form元素你完全可以将它理解为是一个袋子,将所有用户输入数据到装在它里面之后用 来提交回服务端处理,但对于form元素值得注意的是method属性,一般来说有get与post两种方法,其实不要想得太复杂(因为深入的不需要太理解,对于后续的内容没有太多关系,如 有兴趣不妨可以使用浏览器的调试工具查看请求头部信息与发送信息,例如firebug),表现出来就是,使用get提交表单的话所有的input元素的值将会在地址栏处出现,而post则不会, 例如使用get提交此表单后的浏览器地址栏
代码如下 | 复制代码 |
http://localhost/mytest/token/form.php?data=test&submit=%E6%8F%90%E4%BA%A4 |
post则在 地址栏看不到了,使用fiebug可以看到如下信息
可以简单认为get是显式传送数据的,而 post则是隐式传送数据的,但还有一个很大区别的是post支持更多更大的数据传送。
Next,当表单代码写好了,那么让我们来进行服务器脚本的编写(这里就是PHP)。很简单 ~
代码如下 | 复制代码 |
if ( isset( $_POST['submit'] ) ) { //表单提交处理 $data = isset( $_POST['data'] ) ? htmlspecialchars( $_POST['data'] ) : ''; //Insert or Update数据库 $sql = "insert into test (`string`) values ('$data')"; //do query echo $sql; } ?> |
因为这里是post传送数据的,所以使用PHP的$_POST全局变量就能获取到表单提交的数据,所有使用post方法的表单数据提交到服务端都会被保存在这个$_POST全局变 量中,不妨可以试试print_r( $_POST )这个变量你就明白了。
首先检查一下是否在$_POST数组里面存在submit,如果存在则证明是表单提交过来的,正如asp.net中好像有个 叫ispostback的一样,只是这样没那么严谨而已,但是不要紧之后会解决这个问题的。
之后接收输入框的数据,就是$_POST['data'],别忘了使用htmlspecialchars对这个进 行一下html过滤,因为防止输入了html标签或javascript造成问题(貌似叫做XSS漏洞)。最后就是拼接到sql语句中送入数据库跑了(只是这里paperen并没有很详细使用一些操作数据库的 函数例如mysql_query,有兴趣自己完成它)。恭喜,到了这里你已经顺利地完成了一个数据录入的功能了,但是有个地方你总得改善吧,插入数据后总得给操作者一个提示吧~~至少提示 我操作失败还是成功。所以整个代码paperen写成以下样子。
代码如下 | 复制代码 |
if ( isset( $_POST['submit'] ) ) {
&& $state ) { //数据插入成功 ?>
插入成功 返回
作 ?>
|
html的声明与head还有body都省略了,对比于一开始的代码其实主要是实现了真正插入数据库动作与给出 了操作反馈(通过$state变量),不妨自己拷贝代码然后试试(当然请根据自己实际情况修改数据库操作部分的代码)。代码正常,逻辑没问题,但是有个问题,就是在显示插入成功后再刷新页 面又会执行了表单处理动作,又插了一遍数据!这就是所谓的重复插入问题。在放出解决方案之前您可以自己思考一下该如何解决。
你会不会认为是接收数据与显示处理结果都是 这个页面所以才会导致这个问题?也对,也可以这么认为,使用一些调试工具你会发现,浏览器还对post的数据进行了保留,故在提交完表单后再刷新的话该post数据会重新提交了一遍。
如果有办法将浏览器的这个临时保存的post数据清空掉不就解决问题了,但服务端是没法 做到这点的,因为这是浏览器自身的事情,要么我们就重定向了不然再刷新还是会重复提交数据。
到目前为止也许你已经了解到重复提交的意思与问题的恶劣所在,如果 你不是选用重定向的办法那么就得另外想一个办法了,所以令牌解决办法就是这么过来的。
正如令牌本身代表着权限,操作权,身份标志等等,所以我能不能为我的表单加上这么 一个身份标志,在客户端每次请求这个表单的时候同时生成一个令牌其挂钩,在提交时再进行判断,正确则接收并处理表单。实现本质就是如此,而反映到具体实现上,就需要用到一种叫 session的东西。关于session的解析,参见wiki
简单的理解就是session也是一种令 牌的概念,所以你可能会很惊奇,“什么我已经使用了令牌?!”,是的,但是我们要实现的不仅仅是session而是在其基础上附加一些数据来实现我们想要的表单令牌。So let's do it!
session在php中也是被存放在$_SESSION这个超级全局变量里面的,启用起请使用session_start(),关于其他服务端脚本原理一样,只是可能调用方法名不一致而已。加入 token后的代码如下:
代码如下 | 复制代码 |
//开启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; } ?> 插入成功 返回 |
部分代码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类文件代码
代码如下 | 复制代码 |
class Welcome extends CI_Controller {
public function token() //生成表单令牌 //form example |
form_validation_token
代码如下 | 复制代码 |
/** /** /** /** public function __construct() /** /** /** //提交的hash if ( md5( $source_hash ) == $post_formhash ) /** |

PHP是一种服务器端脚本语言,用于动态网页开发和服务器端应用程序。1.PHP是一种解释型语言,无需编译,适合快速开发。2.PHP代码嵌入HTML中,易于网页开发。3.PHP处理服务器端逻辑,生成HTML输出,支持用户交互和数据处理。4.PHP可与数据库交互,处理表单提交,执行服务器端任务。

PHP在过去几十年中塑造了网络,并将继续在Web开发中扮演重要角色。1)PHP起源于1994年,因其易用性和与MySQL的无缝集成成为开发者首选。2)其核心功能包括生成动态内容和与数据库的集成,使得网站能够实时更新和个性化展示。3)PHP的广泛应用和生态系统推动了其长期影响,但也面临版本更新和安全性挑战。4)近年来的性能改进,如PHP7的发布,使其能与现代语言竞争。5)未来,PHP需应对容器化、微服务等新挑战,但其灵活性和活跃社区使其具备适应能力。

PHP的核心优势包括易于学习、强大的web开发支持、丰富的库和框架、高性能和可扩展性、跨平台兼容性以及成本效益高。1)易于学习和使用,适合初学者;2)与web服务器集成好,支持多种数据库;3)拥有如Laravel等强大框架;4)通过优化可实现高性能;5)支持多种操作系统;6)开源,降低开发成本。

PHP没有死。1)PHP社区积极解决性能和安全问题,PHP7.x提升了性能。2)PHP适合现代Web开发,广泛用于大型网站。3)PHP易学且服务器表现出色,但类型系统不如静态语言严格。4)PHP在内容管理和电商领域仍重要,生态系统不断进化。5)通过OPcache和APC等优化性能,使用OOP和设计模式提升代码质量。

PHP和Python各有优劣,选择取决于项目需求。1)PHP适合Web开发,易学,社区资源丰富,但语法不够现代,性能和安全性需注意。2)Python适用于数据科学和机器学习,语法简洁,易学,但执行速度和内存管理有瓶颈。

PHP用于构建动态网站,其核心功能包括:1.生成动态内容,通过与数据库对接实时生成网页;2.处理用户交互和表单提交,验证输入并响应操作;3.管理会话和用户认证,提供个性化体验;4.优化性能和遵循最佳实践,提升网站效率和安全性。

PHP在数据库操作和服务器端逻辑处理中使用MySQLi和PDO扩展进行数据库交互,并通过会话管理等功能处理服务器端逻辑。1)使用MySQLi或PDO连接数据库,执行SQL查询。2)通过会话管理等功能处理HTTP请求和用户状态。3)使用事务确保数据库操作的原子性。4)防止SQL注入,使用异常处理和关闭连接来调试。5)通过索引和缓存优化性能,编写可读性高的代码并进行错误处理。

在PHP中使用预处理语句和PDO可以有效防范SQL注入攻击。1)使用PDO连接数据库并设置错误模式。2)通过prepare方法创建预处理语句,使用占位符和execute方法传递数据。3)处理查询结果并确保代码的安全性和性能。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器