文档章节

PHP_009 表单验证

g00m
 g00m
发布于 2015/03/01 23:54
字数 2280
阅读 28
收藏 0

表单处理

当处理 HTML 表单时,PHP 能把来自 HTML 页面中的表单元素自动变成可供 PHP 脚本使用。

实例

下面的实例包含了一个 HTML 表单,带有两个输入框和一个提交按钮:

<html>
<body>
<form action="welcome.php" method="post">
Name: <input type="text" name="fname">
Age: <input type="text" name="age">
<input type="submit">
</form>
</body>
</html>

当用户填写完上面的表单并点击提交按钮时,表单的数据会被送往名为 "welcome.php" 的 PHP 文件:

"welcome.php" 文件如下所示:

<html>
<body>
Welcome <?php echo $_POST["fname"]; ?>!<br>
You are <?php echo $_POST["age"]; ?> years old.
</body>
</html>

输出如下所示:

Welcome John!
You are 28 years old.

表单验证

应该在任何可能的时候对用户输入进行验证(通过客户端脚本)。浏览器验证速度更快,并且可以减轻服务器的负载。

如果用户输入需要插入数据库,您应该考虑使用服务器验证。在服务器验证表单的一种好的方式是,把表单传给它自己,而不是跳转到不同的页面。这样用户就可以在同一张表单页面得到错误信息。用户也就更容易发现错误了。


先看看纯HTML的表单代码: 

文本字段

name, email, 及 website 字段为文本输入元素, comment 字段是 textarea。HTML代码如下所示:

Name: <input type="text" name="name">
E-mail: <input type="text" name="email">
Website: <input type="text" name="website">
Comment: <textarea name="comment" rows="5" cols="40"></textarea>

单选按钮

gender 字段是单选按钮,HTML代码如下所示:

Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male

表单元素

HTML 表单代码如下所示::

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

该表单使用 method="post" 方法来提交数据。

上述表单验证规则如下:

字段 验证规则
Name 必须。 +只能包含字母和空格
E-mail 必须。 + 必须是一个有效的电子邮件地址(包含'@'和'.')
Website 必须。如果存在,它必须包含一个有效的URL
Comment 必须。 多行输入字段(文本域)
Gender 必须。 必须选择一个

$_SERVER["PHP_SELF"]是超级全局变量,返回当前正在执行脚本的文件名,与 document root相关。

所以, $_SERVER["PHP_SELF"] 会发送表单数据到当前页面,而不是跳转到不同的页面。

htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。

预定义的字符是:

  • & (和号) 成为 &amp;

  • " (双引号) 成为 &quot;

  • ' (单引号) 成为 &#039;

  • < (小于) 成为 &lt;

  • > (大于) 成为 &gt;


当黑客使用跨网站脚本的HTTP链接来攻击时,$_SERVER["PHP_SELF"]服务器变量也会被植入脚本。原因就是跨网站脚本是附在执行文件的路径后面的,因此$_SERVER["PHP_SELF"]的字符串就会包含HTTP链接后面的JavaScript程序代码。

指定以下表单文件名为 "test_form.php":

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

现在,我们使用URL来指定提交地址 "http://www.demo.com/test_form.php",以上代码修改为如下所示:

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

这样做就很好了。

但是,考虑到用户会在浏览器地址栏中输入以下地址:

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

In this case, the above code will be translated to:

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

代码中添加了 script 标签,并添加了alert命令。 当页面载入时会执行该Javascript代码(用户会看到弹出框)。 这仅仅只是一个简单的实例来说明PHP_SELF变量会被黑客利用。

黑客可以利用这点重定向页面到另外一台服务器的页面上,页面代码文件中可以保护恶意代码,代码可以修改全局变量或者获取用户的表单数据

避免 $_SERVER["PHP_SELF"] 被利用

$_SERVER["PHP_SELF"] 可以通过 htmlspecialchars() 函数来避免被利用。

form 代码如下所示:

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

htmlspecialchars() 把一些预定义的字符转换为 HTML 实体。现在如果用户想利用 PHP_SELF 变量, 结果将输出如下所示:

<form method="post" action="test_form.php/&quot;&gt;&lt;script&gt;alert('hacked')&lt;/script&gt;">

尝试该漏洞失败!

PHP 验证表单数据

我们对用户所有提交的数据都通过 PHP 的 htmlspecialchars() 函数处理。

当我们使用 htmlspecialchars() 函数时,在用户尝试提交以下文本域:

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

- 该代码将不会被执行,因为它会被保存为HTML转义代码,如下所示:

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

以上代码是安全的,可以正常在页面显示或者插入邮件中。

当用户提交表单时,我们将做以下两件事情,:

  1. 使用 PHP trim() 函数去除用户输入数据中不必要的字符 (如:空格,tab,换行)。

  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;
}
?>

注意我们在执行以上脚本时,会通过$_SERVER["REQUEST_METHOD"]来检测表单是否被提交 。如果 REQUEST_METHOD 是 POST, 表单将被提交 - 数据将被验证。如果表单未提交将跳过验证并显示空白。

在以上实例中使用输入项都是可选的,即使用户不输入任何数据也可以正常显示。


完善

在以下代码中我们加入了一些新的变量: $nameErr, $emailErr, $genderErr, 和 $websiteErr.。这些错误变量将显示在必须字段上。 我们还为每个$_POST变量增加了一个if else语句。 这些语句将检查 $_POST 变量是 否为空(使用php的 empty() 函数)。如果为空,将显示对应的错误信息。 如果不为空,数据将传递给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>

邮件和URL验证

验证名称

以下代码将通过简单的方式来检测 name 字段是否包含字母和空格,如果 name 字段值不合法,将输出错误信息:

$name = test_input($_POST["name"]);

if (!preg_match("/^[a-zA-Z ]*$/",$name))  //字母开头,字母结尾

  {

  $nameErr = "只允许字母及空格";
 

  }

preg_match — 进行正则表达式匹配。

语法:

int preg_match ( string $pattern , string $subject [, array $matches [, int $flags ]] )


在 subject 字符串中搜索与 pattern 给出的正则表达式相匹配的内容。如果提供了 matches ,则其会被搜索的结果所填充。$matches[0] 将包含与整个模式匹配的文本,$matches[1] 将包含与第一个捕获的括号中的子模式所匹配的文本,以此类推。


验证邮件

以下代码将通过简单的方式来检测 e-mail 地址是否合法。如果 e-mail 地址不合法,将输出错误信息:

$email = test_input($_POST["email"]);

if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))

  {

  $emailErr = "非法邮件地址";
 

  }

验证 URL

以下代码将检测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";
 

  }

代码

<?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"]);
    // check if name only contains letters and whitespace
    if (!preg_match("/^[a-zA-Z ]*$/",$name))
      {
      $nameErr = "Only letters and white space allowed"; 
      }
    }

  if (empty($_POST["email"]))
    {$emailErr = "Email is required";}
  else
    {
    $email = test_input($_POST["email"]);
    // check if e-mail address syntax is valid
    if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email))
      {
      $emailErr = "Invalid email format"; 
      }
    }

  if (empty($_POST["website"]))
    {$website = "";}
  else
    {
    $website = test_input($_POST["website"]);
    // check if URL address syntax is valid (this regular expression also allows dashes in the URL)
    if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website))
      {
      $websiteErr = "Invalid URL"; 
      }
    }

  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"]);}
}
?>

本文转载自:

共有 人打赏支持
g00m
粉丝 5
博文 51
码字总数 37146
作品 0
广州
Laravel5.2之Validator

引言: Laravel提供了Validator模块,可解决表单提交验证等一些需求,并且可以在视图View中显示错误验证信息,交互还是很友好的。注明:作者水平有限,有错误或建议请指正,轻拍。 概述: La...

botkenni
2016/10/10
50
0
10个强大的Javascript表单验证插件推荐

创建一个JavaScript表单验证插件,可以说是一个繁琐的过程,涉及到初期设计、开发与测试等等环节。实际上一个优秀的程序员不仅是技术高手,也应该是善假于外物的。本文介绍了10个不错的JavaS...

小鲅鱼
2012/04/20
40.8K
4
强力推荐10款Javascript表单验证插件

【IT168 技术】创建一个JavaScript表单验证插件,可以说是一个繁琐的过程,涉及到初期设计、开发与测试等等环节。实际上一个优秀的程序员不仅是技术高手,也应该是善假于外物的。本文介绍了1...

开源中国
2012/04/20
0
0
Laravel中使用FormRequest进行表单验证及对验证异常进行自定义处理

所有示例基于 今天天气不错,我们来说说表单验证。 Controller中做表单验证 有的同学把表单验证逻辑写在Controller中,例如这个对用户提交评论内容的验证: 这样写的话,表单验证和业务逻辑挤...

该叶无法找到
2016/06/16
455
3
PHP 表单验证

1.通过PHP来验证表单数据 <!DOCTYPE HTML> <html><head></head><body> <?php// define variables and set to empty values$name = $email = $gender = $comment = $website = ""; if ($SERV......

伟俊22
2016/02/24
54
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java并发备忘

不安全的“先检查后执行”,代码形式如下: if(条件满足){ //这里容易出现线程安全问题//doSomething}else{//doOther} 读取-修改-写入 原子操作:使用CAS技术,即首先从V中读取...

Funcy1122
今天
0
0
SpringBoot2.0 停机

最近新建了个SpringBoot2.0的项目,因为原来一直使用的是传统的Tomcat部署war包的形式,所以这次SpringBoot内置Tomcat部署jar包的时候遇到了很多问题。其中一个就是因为没有外置的Tomcat容器...

Canaan_
昨天
0
1
Confluence 6 外部参考

一个外部参考的意思是任何站点链接到你 Confluence 的实例。任何时候当 Confluence 的用户单击这个外部链接的时候,Confluence 可以记录这次单击为参考。 在默认的情况下,外部链接的参考链接...

honeymose
昨天
0
0
Android中的设计模式之抽象工厂模式

参考 《设计模式解析》 第十一章 Abstract Factory模式 《设计模式:可复用面向对象软件的基础 》3.1 Abstract Factory 抽象工厂 对象创建型模式 《Android源码设计模式解析与实战》第6章 创...

newtrek
昨天
0
0
Redis | 地理空间(GEO)的一个坑

Redis的地理空间(Geo)是个好东西,轻轻松松的就可以把地图描点的问题处理了, 最近却遇到一个坑...Redis采用的Msater-Slave模式, 运用GEORADIUS在salve读取对应的数据,新增了从节点但是从不返...

云迹
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部