前面的话

  在以前,网站的用户与后端交互的主要方式是通过HTML表单的使用。表单的引入在1993年,由于其简单性和易用性,直到电子商务出现之前一直保持着重要位置。理解表单提交,对于更深入地理解ajax是有好处的。下面将详细介绍表单形式的交互

建立表单

  表单处理是一个多线程。首先创建一个表单,以供用户输入详细的请求信息。接着,输入的数据被发送到网页服务器,在服务器里这些数据得到编译和错误检测。如果PHP代码标识出一个或多个需要重要输入的字段,则带有相关错误信息的表单会重新显示。当精确的输入信息满足代码的需要时,代码会采取一些调用数据库的行为,如输入购物的细节

  [注意]关于HTML表单元素的详细信息移步至此

  要建立一个表单,至少需要以下几个元素:一个form元素、一个指定GET或POST方法的提交类型、一个或多个输入字段,以及表单数据提交的目的地址URL

<form action="http://www.w3school.com.cn/demo/welcome.php">
<span>Name:</span>
<input name="name"><br>
<span>Email:</span>
<input name="email"><br>
<input type="submit">
</form>

表单处理

  PHP 超全局变量 $_GET 和 $_POST 用于收集表单数据(form-data)

  GET 和 POST 都创建数组(例如,array( key => value, key2 => value2, key3 => value3, ...))。此数组包含键/值对,其中的键是表单控件的名称,而值是来自用户的输入数据。

  GET 和 POST 被视作 $_GET 和 $_POST。它们是超全局变量,这意味着对它们的访问无需考虑作用域,即无需任何特殊代码,能够从任何函数、类或文件访问它们

  $_GET 是通过 URL 参数传递到当前脚本的变量数组

  $_POST 是通过 HTTP POST 传递到当前脚本的变量数组

  通过 GET 方法从表单发送的信息对任何人都是可见的(所有变量名和值都显示在 URL 中)。GET对所发送信息的数量也有限制。限制在大于2000个字符。不过,由于变量显示在 URL 中,把页面添加到书签中也更为方便

  通过 POST 方法从表单发送的信息对其他人是不可见的(所有名称/值会被嵌入 HTTP 请求的主体中),并且对所发送信息的数量也无限制。此外 POST 支持高阶功能,比如在向服务器上传文件时进行 multi-part 二进制输入。不过,由于变量未显示在 URL 中,也就无法将页面添加到书签。一般地,使用 POST 来发送表单数据

【post】

<!-- 提交页 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form method="post" action="http://www.w3school.com.cn/demo/welcome.php">
<span>Name:</span>
<input name="name"><br>
<span>Email:</span>
<input name="email"><br>
<input type="submit">
</form>
</body>
</html>
<!-- 响应页 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
Welcome <?php echo $_POST["name"]; ?><br>
Your email address is: <?php echo $_POST["email"]; ?>
</body>
</html>

【get】

  如果不设置form元素的method属性,则默认为get方法

<!-- 提交页 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form action="http://www.w3school.com.cn/demo/welcome_get.php">
<span>Name:</span>
<input name="name"><br>
<span>Email:</span>
<input name="email"><br>
<input type="submit">
</form>
</body>
</html>
<!-- 响应页 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
Welcome <?php echo $_GET["name"]; ?><br>
Your email address is: <?php echo $_GET["email"]; ?>
</body>
</html>

表单安全

  上面的代码很简单。不过,最重要的内容被漏掉了。需要对表单数据进行验证,以防止脚本出现漏洞

  对 HTML 表单数据进行适当的验证对于防范黑客和垃圾邮件很重要

字段           验证规则
Name   必需。必须包含字母和空格。
E-mail 必需。必须包含有效的电子邮件地址(包含 @ 和 .)
Website 可选。如果选填,则必须包含有效的 URL。
Comment 可选。多行输入字段(文本框)
Gender 必需。必须选择一项。
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

姓名:
<input type="text" name="name" value="">
<span class="error">* </span>
<br><br>
电邮:
<input type="text" name="email" value="">
<span class="error">* </span>
<br><br>
网址:
<input type="text" name="website" value="">
<span class="error"></span>
<br><br>
<label>
评论:
<textarea name="comment" rows="5" cols="40"></textarea>
<br><br>
性别:
<input type="radio" name="gender" value="female">女性
<input type="radio" name="gender" value="male">男性
<span class="error">* </span>
<br><br>
<input type="submit" name="submit" value="提交">
</form>

【$_SERVER["PHP_SELF"]】

  $_SERVER["PHP_SELF"] 是一种超全局变量,它返回当前执行脚本的文件名。因此,$_SERVER["PHP_SELF"] 将表单数据发送到页面本身,而不是跳转到另一张页面。这样,用户就能够在表单页面获得错误提示信息

【XSS】

  $_SERVER["PHP_SELF"] 变量能够被黑客利用。如果页面使用了PHP_SELF,用户能够输入下划线然后执行跨站点脚本(XSS)

  跨站点脚本(Cross-site scripting,XSS)是一种计算机安全漏洞类型,常见于Web应用程序。XSS能够使攻击者向其他用户浏览的网页中输入客户端脚本

  假设"test_form.php" 的页面中有如下表单

<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">

  现在,如果用户进入的是地址栏中正常的URL:"http://www.example.com/test_form.php",上面的代码会转换为:

<form method="post" action="test_form.php">

  不过,如果用户在地址栏中键入了如下 URL:

http://www.example.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E

  在这种情况下,上面的代码会转换为:

<form method="post" action="test_form.php"/><script>alert('hacked')</script>

  这段代码加入了一段脚本和一个提示命令。并且当此页面加载后,就会执行JavaScript代码(用户会看到一个提示框)。这仅仅是一个关于 PHP_SELF 变量如何被利用的简单无害案例

  <script>标签内能够添加任何JavaScript代码,黑客能够把用户重定向到另一台服务器上的某个文件,该文件中的恶意代码能够更改全局变量或将表单提交到其他地址以保存用户数据等

【htmlspecialchars()】

  如果避免$_SERVER["PHP_SELF"]被利用?通过使用 htmlspecialchars() 函数能够避免$_SERVER["PHP_SELF"]被利用

  htmlspecialchars()函数把特殊字符转换为 HTML 实体。这意味着 < 和 > 之类的HTML字符会被替换为 &lt; 和 &gt;。这样可防止攻击者通过在表单中注入HTML或JavaScript代码(跨站点脚本攻击)对代码进行利用

  表单代码是这样的:

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

  htmlspecialchars()把特殊字符转换为HTML实体。现在,如果用户试图利用PHP_SELF变量,会导致如下输出

<form method="post" action="test_form.php/"><script>alert('hacked')</script>">

  所以,验证表单要做的第一件事是通过PHP的htmlspecialchars()函数传递所有变量。在使用htmlspecialchars()函数后,如果用户试图在文本字段中提交以下内容:

<script>location.href('http://www.hacked.com')</script>

  代码不会执行,因为会被保存为转义代码,就像这样:

&lt;script&gt;location.href('http://www.hacked.com')&lt;/script&gt;

  现在这条代码显示在页面上或e-mail中是安全的

  在用户提交该表单时,我们还要做两件事:1、通过PHP的trim()函数去除用户输入数据中不必要的字符(多余的空格、制表符、换行);2、通过PHP的stripslashes()函数删除用户输入数据中的反斜杠(\)

  接下来我创建一个检查函数,命名为 test_input(),通过test_input()函数检查每个$_POST变量

<?php
// 定义变量并设置为空值
$name = $email = $gender = $comment = $website = ""; if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
} function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>

错误信息

  在下面的代码中增加了一些新变量:$nameErr、$emailErr、$genderErr以及$websiteErr。这些错误变量会保存被请求字段的错误消息。还为每个$_POST变量添加了一个if else语句。这条语句通过PHP的empty()函数检查$_POST变量是否为空。如果为空,则错误消息会存储于不同的错误变量中。如果不为空,则通过test_input()函数发送用户输入数据

<?php
// 定义变量并设置为空值
$nameErr = $emailErr = $genderErr = $websiteErr = "";
$name = $email = $gender = $comment = $website = ""; if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["name"])) {
$nameErr = "Name is required";
} else {
$name = test_input($_POST["name"]);
} if (empty($_POST["email"])) {
$emailErr = "Email is required";
} else {
$email = test_input($_POST["email"]);
} if (empty($_POST["website"])) {
$website = "";
} else {
$website = test_input($_POST["website"]);
} if (empty($_POST["comment"])) {
$comment = "";
} else {
$comment = test_input($_POST["comment"]);
} if (empty($_POST["gender"])) {
$genderErr = "Gender is required";
} else {
$gender = test_input($_POST["gender"]);
}
}
?>

  在 HTML 表单中,在每个被请求字段后面增加了一点脚本。如果需要,会生成恰当的错误消息(如果用户未填写必填字段就试图提交表单)

<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">

Name: <input type="text" name="name">
<span class="error">* <?php echo $nameErr;?></span>
<br><br>
E-mail:
<input type="text" name="email">
<span class="error">* <?php echo $emailErr;?></span>
<br><br>
Website:
<input type="text" name="website">
<span class="error"><?php echo $websiteErr;?></span>
<br><br>
<label>Comment: <textarea name="comment" rows="5" cols="40"></textarea>
<br><br>
Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male
<span class="error">* <?php echo $genderErr;?></span>
<br><br>
<input type="submit" name="submit" value="Submit"> </form>

表单验证

  验证规则中,"Name", "E-mail" 以及 "Gender" 字段是必需的。这些字段不能为空且必须在 HTML 表单中填写

【验证名字】

  以下代码检查name字段是否包含字母和空格。如果name字段无效,则存储一条错误消息

$name = test_input($_POST["name"]);
if (!preg_match("/^[a-zA-Z ]*$/",$name)) {
$nameErr = "只允许字母和空格!";
}

【验证 E-mail】

  以下代码展检查e-mail地址语法是否有效。如果无效则存储一条错误消息

$email = test_input($_POST["email"]);
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)) {
$emailErr = "无效的 email 格式!";
}

【验证 URL】

  以下代码检查URL地址语法是否有效。如果 URL 地址语法无效,则存储一条错误消息

$website = test_input($_POST["website"]);
if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%
=~_|]/i",$website)) {
$websiteErr = "无效的 URL";
}

保留值

  如果需要在用户点击提交按钮后在输入字段中显示值,我们在以下输入字段的value属性中增加了一小段 PHP 脚本:name、email 以及 website。在 comment 文本框字段中,把脚本放到了 <textarea> 与 </textarea> 之间。这些脚本输出$name、$email、$website 和 $comment 变量的值

  然后,还需要显示选中了哪个单选按钮。对此,必须操作 checked 属性(而非单选按钮的 value 属性)

Name: <input type="text" name="name" value="<?php echo $name;?>">

E-mail: <input type="text" name="email" value="<?php echo $email;?>">

Website: <input type="text" name="website" value="<?php echo $website;?>">

Comment: <textarea name="comment" rows="5" cols="40"><?php echo $comment;?></textarea>

Gender:

<input type="radio" name="gender"
<?php if (isset($gender) && $gender=="female") echo "checked";?>
value="female">Female
<input type="radio" name="gender"
<?php if (isset($gender) && $gender=="male") echo "checked";?>
value="male">Male

表单发送

  HTML网页的<form>元素能够以四种格式,向服务器发送数据

  使用POST方法,将enctype属性设为application/x-www-form-urlencoded,这是默认方法

<form action="register.php" method="post" onsubmit="AJAXSubmit(this); return false;"></form>

  使用POST方法,将enctype属性设为text/plain

<form action="register.php" method="post" enctype="text/plain" onsubmit="AJAXSubmit(this); return false;"></form>

  使用POST方法,将enctype属性设为multipart/form-data

<form action="register.php" method="post" enctype="multipart/form-data" onsubmit="AJAXSubmit(this); return false;"></form>

  使用GET方法,enctype属性将被忽略

<form action="register.php" method="get" onsubmit="AJAXSubmit(this); return false;"></form>

  某个表单有两个字段,分别是foo和baz,其中foo字段的值等于bar,baz字段的值是一个分为两行的字符串。上面四种方法,都可以将这个表单发送到服务器

  第一种方法是默认方法,POST发送,Encoding type为application/x-www-form-urlencoded

Content-Type: application/x-www-form-urlencoded
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A

  第二种方法是POST发送,Encoding type为text/plain

Content-Type: text/plain

foo=bar
baz=The first line.
The second line.

  第三种方法是POST发送,Encoding type为multipart/form-data

Content-Type: multipart/form-data; boundary=---------------------------314911788813839

-----------------------------314911788813839
Content-Disposition: form-data; name="foo" bar
-----------------------------314911788813839
Content-Disposition: form-data; name="baz" The first line.
The second line. -----------------------------314911788813839--

  第四种方法是GET请求

?foo=bar&baz=The%20first%20line.%0AThe%20second%20line

完整代码

<!DOCTYPE HTML>
<html>
<head>
<style>
.error {color: #FF0000;}
</style>
</head>
<body> <?php
// 定义变量并设置为空值
$nameErr = $emailErr = $genderErr = $websiteErr = "";
$name = $email = $gender = $comment = $website = ""; if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["name"])) {
$nameErr = "姓名是必填的";
} else {
$name = test_input($_POST["name"]);
// 检查姓名是否包含字母和空白字符
if (!preg_match("/^[a-zA-Z ]*$/",$name)) {
$nameErr = "只允许字母和空格";
}
} if (empty($_POST["email"])) {
$emailErr = "电邮是必填的";
} else {
$email = test_input($_POST["email"]);
// 检查电子邮件地址语法是否有效
if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)) {
$emailErr = "无效的 email 格式";
}
} if (empty($_POST["website"])) {
$website = "";
} else {
$website = test_input($_POST["website"]);
// 检查 URL 地址语法是否有效(正则表达式也允许 URL 中的斜杠)
if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website)) {
$websiteErr = "无效的 URL";
}
} if (empty($_POST["comment"])) {
$comment = "";
} else {
$comment = test_input($_POST["comment"]);
} if (empty($_POST["gender"])) {
$genderErr = "性别是必选的";
} else {
$gender = test_input($_POST["gender"]);
}
} function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?> <p><span class="error">* 必需的字段</span></p>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
姓名:<input type="text" name="name" value="<?php echo $name;?>">
<span class="error">* <?php echo $nameErr;?></span>
<br><br>
电邮:<input type="text" name="email" value="<?php echo $email;?>">
<span class="error">* <?php echo $emailErr;?></span>
<br><br>
网址:<input type="text" name="website" value="<?php echo $website;?>">
<span class="error"><?php echo $websiteErr;?></span>
<br><br>
评论:<textarea name="comment" rows="5" cols="40"><?php echo $comment;?></textarea>
<br><br>
性别:
<input type="radio" name="gender"
<?php if (isset($gender) && $gender=="female") echo "checked";?>
value="female">女性
<input type="radio" name="gender"
<?php if (isset($gender) && $gender=="male") echo "checked";?>
value="male">男性 <span class="error">* <?php echo $genderErr;?></span>
<br><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>

深入理解ajax系列第八篇——表单提交的更多相关文章

  1. 深入理解ajax系列第八篇

    前面的话 在以前,网站的用户与后端交互的主要方式是通过HTML表单的使用.表单的引入在1993年,由于其简单性和易用性,直到电子商务出现之前一直保持着重要位置.理解表单提交,对于更深入地理解ajax是 ...

  2. 深入理解ajax系列第四篇——请求实例

    前面的话 在使用ajax的过程中,常用的请求方式是GET和POST两种.本文将以实例的形式来详细说明这两种请求方式 GET GET是最常见的请求类型,最常用于向服务器查询某些信息.必要时,可以将查询字 ...

  3. 深入理解ajax系列第四篇——FormData

    前面的话 现代Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2级为此定义了FormData类型.FormData为序列化表单以及创建与表单格式相同的数据提供了便利. ...

  4. 深入理解ajax系列第四篇

    前面的话 现代Web应用中频繁使用的一项功能就是表单数据的序列化,XMLHttpRequest 2级为此定义了FormData类型.FormData为序列化表单以及创建与表单格式相同的数据提供了便利. ...

  5. 深入理解ajax系列第三篇——头部信息

    前面的话 每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用.XHR对象提供了操作头部信息的方法.本文将详细介绍HTTP的头部信息 默认信息 默认情况下,在发送XHR请求的同时,还会 ...

  6. 深入理解ajax系列第六篇——头部信息

    前面的话 每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用.XHR对象提供了操作头部信息的方法.本文将详细介绍HTTP的头部信息 默认信息 默认情况下,在发送XHR请求的同时,还会 ...

  7. 深入理解ajax系列第六篇

    前面的话 每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用.XHR对象提供了操作头部信息的方法.本文将详细介绍HTTP的头部信息 默认信息 默认情况下,在发送XHR请求的同时,还会 ...

  8. ajax传递数组、form表单提交对象数组

    在JSP页面开发中,我们常常会用到form表单做数据提交,由于以前一直只是使用form表单提交单个对象,只要表单文本域的name值和接收的对象的属性名一致,那么传值就没有什么问题.不过,在前几天的开发 ...

  9. 深入学习jQuery选择器系列第七篇——表单选择器

    × 目录 [1]表单元素 [2]对象属性 前面的话 无论是提交还是传递数据,表单元素在动态交互页面的作用是非常重要的.jQuery专门加入了表单选择器,从而能够极其方便地获取到某个类型的表单元素 表单 ...

随机推荐

  1. javascript实现拖曳与拖放图片

    javascript实现拖曳与拖放图片 其实对于drag和drop拖曳与拖放事件IE很早以前就支持这个操作了,我们先来看看HTML5中新增的拖放API. 在HTML5中想要实现拖放操作,至少要做以下操 ...

  2. BT5R3蛋疼的metasploit升级

    刚装了BT5R3,急着想把metasploit升级,原版本是4.5.0,试了网上的各种方法,终于试到了个能成功的,再次记录一下. 系统环境:BT5 R3 1.apt-get update 2.apt- ...

  3. ceph状态信息靠谱查询

    1)检查集群的状态汇总信息: [root@haha1 clouder]# ceph -s cluster 8e136e25-77ab-4e0b-b24b-232a7b466cfe health HEA ...

  4. FFMpeg笔记(七) 代码结构分析,以HLS为例

    HLS流在播放时是先解协议(hls.c)后解封装(mpegts.c),libavformat下的hls.c和mpegts.c实际上是同一个级别的,同属于demuxer. 一.解HLS协议 1. FFm ...

  5. day 43

    今日内容 1.视图 2.事务 3.SQL注入问题 4.存储过程 首先回顾一下昨天所学 子查询: in (select a where 字段名 in select b) exists(判断后面语句执行结 ...

  6. URL最大长度

    今天在测试Email Ticket的时候发现在进行Mark as Read/Unread操作时,请求是通过GET方式进行的.URL中列出了所有参与该操作的Ticket Id.于是,我想起GET请求是有 ...

  7. 虚拟机上不能使用CUDA

    虚拟机的显卡是虚拟的,不能使用CUDA(至少很难),搞了一天才晃过神来: lspci 查找目前主机的硬件配备 用 grep -i 进行大小写无关的搜索

  8. selenium常用命令

    openopen(url)- 在浏览器中打开URL,可以接受相对和绝对路径两种形式type type(inputLocator, value)- 模拟人手的输入过程,往指定的input中输入值- 也适 ...

  9. memcached 和redis比较

    同属于NOSQL存储,网上流传很多memcached能做的是redis都可以做,为什么基本现在两种都火,原因他们有各自擅长的地方. memcahed内部采用多核模式,单列运行很快.memcached采 ...

  10. JMeter:生成漂亮的接口/压力测试的HTML报告

    JMeter生成HTML网页报告(非gui模式操作) 我们做性能测试的时候会经常使用一些性能测试工具,比如loardrunner和jmeter,我个人比较喜欢Jmeter这个工具,jmeter之前版本 ...