【前言】
在之前文章PHP表单教程(1) 的基础上,今天继续总结PHP表单相关的知识点,在这里记录总结下
【列表】
(1)表单验证安全相关
包含PHP表单安全性,超全局变量$_SERVER["PHP_SELF"] ,htmlspecialchars(特殊字符) 函数
(2)验证表单数据
(3)表单必填验证及错误提示
(4)表单数据验证及错误提示
(5)防止表单提交数据后清空
(6)完整的表单实例
【主体】
(1)表单验证安全相关
处理PHP表单时安全性十分重要,下面介绍下如何安全的处理PHP表单。
对于HTML表单信息进行适当验证,对于防止垃圾信息和黑客十分重要。
①表单验证案例
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> Name: <input type="text" name="name"><br> E-mail: <input type="text" name="email"><br> Website: <input type="text" name="website"><br> Comment: <textarea name="comment" rows="5" cols="40"></textarea><br> Gender: <input type="radio" name="gender" value="female">Female <input type="radio" name="gender" value="male">Male </form>
当提交此表单时,通过 method="post" 发送表单数据
②什么是 $_SERVER["PHP_SELF"] 变量?
$_SERVER["PHP_SELF"] 是一种超全局变量,它返回当前执行脚本的文件名。因此,会将表单数据发送到页面本身,而不是跳转到另一张页面。这样,用户就能够在表单页面获得错误提示信息。
③什么是 htmlspecialchars() 函数?
把特殊字符转换为 HTML 实体的函数。这意味着 < 和 > 之类的 HTML 字符会被替换为 < 和 > 。这样可防止攻击者通过在表单中注入 HTML 或 JavaScript 代码(跨站点脚本攻击)对代码进行利用。下面针对网站安全性来做下介绍
④PHP 表单安全性
$_SERVER["PHP_SELF"] 变量能够被黑客利用!如果您的页面使用了 PHP_SELF,用户能够输入下划线然后执行跨站点脚本(XSS),关于XSS我在后面文章做介绍
黑客可以在地址栏中键入更改的URL,在其后植入一段脚本,当此页面加载后,就会执行代码。而且<script> 标签内能够添加任何JS代码(15-50k)!黑客能够把用户重定向到另一台服务器上的某个文件,该文件中的恶意代码能够更改全局变量或将表单提交到其他地址以保存用户数据,等等
注意:不要用Chrome测试,因为Chrome会自动拦截,踩了一下午坑才查出来问题是浏览器拦截
⑤如果避免 $_SERVER["PHP_SELF"] 被利用?
通过使用 htmlspecialchars(html特殊字符) 函数能够避免 $_SERVER["PHP_SELF"] 被利用,
原理:htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体,如果用户试图利用 PHP_SELF 变量,会输出实体字符,使得植入的脚本无法执行
& (和号) 成为 &
" (双引号) 成为 "
' (单引号) 成为 '
< (小于) 成为 <
> (大于) 成为 >
(2)验证表单数据
了解了表单验证安全相关后,我们要做的第一件事是通过 PHP 的 htmlspecialchars() 函数传递所有变量。
在我们使用 htmlspecialchars() 函数后,如果用户试图在文本字段中提交以下内容:
<script>location.href('http://www.baidu.com')</script>
即使这样导入脚本,代码不会执行,因为会被保存为转义代码,就像这样:
<script>location.href('http://www.hacked.com')</script>
在用户提交该表单时,我们还要做两件事:
①去除用户输入数据中不必要的字符(多余的空格、制表符、换行,通过 PHP trim() 函数)
②删除用户输入数据中的反斜杠(\,通过 PHP stripslashes() 函数)
接下来我们创建一个检查函数test_input(相比一遍遍地写代码,这样效率更好)。现在,我们能够通过 test_input() 函数检查每个 $_POST 变量,脚本是这样的:
案例:
<!DOCTYPE html> <html> <title>PHP测试demo</title> <style type="text/css"> *{margin:0;padding:0} </style> <body> <?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; } ?> <h2>PHP 验证实例</h2> <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 姓名:<input type="text" name="name"> <br><br> 电邮:<input type="text" name="email"> <br><br> 网址:<input type="text" name="website"> <br><br> 评论:<textarea name="comment" rows="5" cols="40"></textarea> <br><br> 性别: <input type="radio" name="gender" value="female">女性 <input type="radio" name="gender" value="male">男性 <br><br> <input type="submit" name="submit" value="提交"> </form> <?php echo "<h2>您的输入:</h2>"; echo $name."<br>"; echo $email."<br>"; echo $website."<br>"; echo $comment."<br>"; echo $gender; ?> </body> </html>
代码详解:
①超全局变量$_SERVER的元素$_SERVER['REQUEST_METHOD'],作用:返回访问页面使用的请求方法(例如 POST)
②$_POST 变量用于收集来自 method=”post” 的表单中的值
$_POST 变量是一个数组,内容是由 HTTP POST 方法发送的变量名称和值。$_POST 变量用于收集来自 method=”post” 的表单中的值,带有 POST 方法的表单发送的信息,任何人都是不可见的(不会显示在浏览器的地址栏),并且对发送信息的量也没有限制
(3)表单必填验证及错误提示
在上面的例子中,所有输入字段都是可选的。即使用户未输入任何数据,脚本也能正常工作。接下来制作必填输入字段,并创建需要时使用的错误消息。
在下面的代码中我们增加了新变量:$nameErr。错误变量会保存被请求字段的错误消息,接下来为每个 $_POST 变量添加了一个 if else 语句。这条语句检查 $_POST 变量是否为空(通过 PHP empty() 函数)。如果为空,则错误消息会存储于不同的错误变量中。如果不为空,则通过 test_input() 函数发送用户输入数据:
案例:
<!DOCTYPE html> <html> <title>PHP测试demo</title> <style type="text/css"> *{margin:0;padding:0} .error {color: #FF0000;} </style> <body> <?php // 定义变量并设置为空值 $nameErr = = ""; $name = = ""; if ($_SERVER["REQUEST_METHOD"] == "POST") { if (empty($_POST["name"])) { $nameErr = "姓名是必填的"; } else { $name = test_input($_POST["name"]); } } function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; } ?> <h2>PHP 验证实例</h2> <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 姓名:<input type="text" name="name"> <span class="error">* <?php echo $nameErr;?></span><br> <input type="submit" name="submit" value="提交"> </form> <?php echo "<h2>您的输入:</h2>"; echo $name; ?> </body> </html>详解:
上个案例,还有一个问题:检验数据的函数放到HTML布局标签后的时候,会运行异常,暂未解决疑惑??
(4)表单数据验证及错误提示
接下来是验证具体输入数据,例如“Name 字段是否只包含字母和空格?”,以及“E-mail 字段是否包含有效的电子邮件地址语法?”,并且如果填写了 Website 字段,“这个字段是否包含了有效的 URL?”等
例如验证名字:
以下代码展示的简单方法检查 name 字段是否包含字母和空格。如果 name 字段无效,则存储一条错误消息。preg_match() 函数检索字符串的模式,如果模式存在则返回 true,否则返回 false
if ($_SERVER["REQUEST_METHOD"] == "POST") { $name = test_input($_POST["name"]); if (!preg_match("/^[a-zA-Z ]*$/",$name)) {//检索字符串的模式 $nameErr = "只允许字母和空格!"; }else if(empty($name)){ $nameErr = "不允许为空"; }else{ $name = test_input($_POST["name"]); } }注意:除了if...elseif....else 条件语句执行,我还试过switch,不过有局限性(switch只能传递一个值)
(5)接下来讲解下如何防止表单在用户提交表单后清空所有输入字段
以下为提交表单后保留输入字段中的值详解
如果想保留显示提交的数据,仅需在输入字段的 value 属性中增加一小段 PHP 脚本即可,例如
姓名:<input type="text" name="name" value="<?php echo $_POST["name"]?>">另外附上一段防止单选清空的代码:
<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<br>代码解析:isset()一般用来检测变量是否设置,例如单选是否选定状态
(6)完整的表单实例
<!DOCTYPE HTML> <html> <head> <title>PHP测试demo</title> <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; } ?> <h2>PHP 验证实例</h2> <p><span class="error">* 必需的字段</span></p> <form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 姓名:<input type="text" name="name"> <span class="error">* <?php echo $nameErr;?></span> <br><br> 电邮:<input type="text" name="email"> <span class="error">* <?php echo $emailErr;?></span> <br><br> 网址:<input type="text" name="website"> <span class="error"><?php echo $websiteErr;?></span> <br><br> 评论:<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">* <?php echo $genderErr;?></span> <br><br> <input type="submit" name="submit" value="提交"> </form> <?php echo "<h2>您的输入:</h2>"; echo $name."<br>"; echo $email."<br>"; echo $website."<br>"; echo $comment."<br>"; echo $gender; ?> </body> </html>
【总结】
(1)PHP常用函数
①empty()检验是否为空;
对比:isset()一般用来检测变量是否设置,例如单选是否选定状态
②htmlspecialchars() 把一些预定义的字符转换为 HTML 实体
③trim()去除输入数据中不必要的字符(多余的空格、制表符、换行)
④stripslashes()去除输入数据中的反斜杠(\)
⑤preg_match() 检索字符串的模式,如果模式存在则返回 true,否则返回 false
(2)变量
①预定义的 $_POST 变量用于收集来自 method="post" 的表单中的值
②超全局变量$_SERVER,许多属性,以下列举了几个常见的
③$_SERVER["PHP_SELF"] 是一种超全局变量,它返回当前执行脚本的文件名
④$_SERVER['REQUEST_METHOD']超全局变量,返回访问页面使用的请求方法(例如 POST)
.