一、表单简介
表单(Form)在网页中主要负责数据采集功能。
一个表单有三个基本组成部分:
表单标签:这里面包含了处理表单数据所用CGI(公共网关接口)程序的URL以及数据提交到服务器的方法。
表单域:包含了文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉选择框和文件上传框等。
表单按钮:包括提交按钮、复位按钮和一般按钮;用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作。
二、表单验证实例
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>表单验证实例(信息收集)</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"])) // 使用empty()函数检测如为空,将显示对应的错误信息
{
$nameErr = "名字是必需的";
}
else
{
$name = test_input($_POST["name"]);
// 检测名字是否只包含大小写字母跟空格,preg_match进行正则表达式匹配
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 = "非法邮箱格式";
}
}
if (empty($_POST["website"]))
{
$website = "";
}
else
{
$website = test_input($_POST["website"]);
// 检测 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) // 将过滤函数写在自定义函数test_input()中,以提高代码的复用性
{
$data = trim($data); // 去除输入数据中不必要的字符(如:空格,tab,换行)。
$data = stripslashes($data); // 去除输入数据中的反斜杠 (\)
$data = htmlspecialchars($data);
return $data;
}
?>
<h2>PHP 表单验证实例</h2>
<p><span class="error">* 必需字段。</span></p>
<!--
该表单使用 method="post" 方法来提交数据。
$_SERVER["PHP_SELF"]是超级全局变量,返回当前正在执行脚本的文件名,会发送表单数据到当前页面,而不是跳转到不同的页面。
htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。
预定义的字符是:
& (和号) 成为 &
" (双引号) 成为 "
' (单引号) 成为 '
< (小于) 成为 <
> (大于) 成为 >
-->
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<!--"名字"、"E-mail"、"网址"字段为文本输入元素,"备注"字段是 textarea(标签定义多行的文本输入控件)-->
名字: <input type="text" name="name" value="<?php echo $name;?>">
<span class="error">* <?php echo $nameErr;?></span>
<br><br>
E-mail: <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="Submit">
</form>
<?php
echo "<h2>您输入的内容是:</h2>";
echo $name;
echo "<br>";
echo $email;
echo "<br>";
echo $website;
echo "<br>";
echo $comment;
echo "<br>";
echo $gender;
?>
</body>
</html>
三、$_SERVER[“PHP_SELF”] 变量的跨站脚本利用与避免
当黑客使用跨网站脚本的HTTP链接来攻击时,$_SERVER["PHP_SELF"]
服务器变量也会被植入脚本。
因为跨网站脚本附在执行文件的路径后面,$_SERVER["PHP_SELF"]
的字符串会包含HTTP链接后面的JavaScript程序代码。
任何JavaScript代码可以添加在<script>
标签中!
黑客可以利用这点重定向页面到另外一台服务器的页面上,用恶意代码修改全局变量或者获取用户的表单数据。
例如要指定以下表单文件名为 “test_form.php
”:
<form method="post" action="<?php echo $_SERVER["PHP_SELF"];?>">
如使用URL来指定提交地址 “test_form.php”,将以上代码修改为:
<form method="post" action="test_form.php">
黑客在浏览器地址栏中输入:
http://www.xxx.com/test_form.php/%22%3E%3Cscript%3Ealert('hacked')%3C/script%3E
以上的 URL 中,将被解析为如下代码并执行:
<form method="post" action="test_form.php/"><script>alert('hacked')</script>
代码中添加了 script 标签,并添加了alert命令。 当页面载入时会执行该Javascript代码(用户会看到弹出框)。
$_SERVER["PHP_SELF"]
可以通过 htmlspecialchars() 函数来避免被利用:
<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>">