PHP 表单验证

作者: 幸宇 | 来源:发表于2018-03-20 08:37 被阅读54次
    什么是 $_SERVER["PHP_SELF"] 变量?

    $_SERVER["PHP_SELF"] 是一种超全局变量,它返回当前执行脚本的文件名。

    因此,$_SERVER["PHP_SELF"] 将表单数据发送到页面本身,而不是跳转到另一张页面。这样,用户就能够在表单页面获得错误提示信息。

    什么是 htmlspecialchars() 函数?

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

    关于 PHP 表单安全性的重要提示

    $_SERVER["PHP_SELF"] 变量能够被黑客利用!

    如果您的页面使用了 PHP_SELF,用户能够输入下划线然后执行跨站点脚本(XSS)又叫css。

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

    假设我们的一张名为 "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.php.cn/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代码(用户会看到弹出框)。 这仅仅只是一个简单的实例来说明PHP_SELF变量会被黑客利用。

    请注意, 任何JavaScript代码可以添加在<script>标签中! 黑客可以利用这点重定向页面到另外一台服务器的页面上,页面 代码文件中可以保护恶意代码,代码可以修改全局变量或者获取用户的表单数据。

    如何避免 $_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/"><script>alert('hacked')</script>">
    尝试该漏洞失败!

    通过 PHP 验证表单数据

    我们要做的第一件事是通过 PHP 的 htmlspecialchars() 函数传递所有变量。

    在我们使用 htmlspecialchars() 函数后,如果用户试图在文本字段中提交以下内容:

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

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

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

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

    在用户提交该表单时,我们还要做两件事:

    1. (通过 PHP trim() 函数)去除用户输入数据中不必要的字符(多余的空格、制表符、换行)

    2. (通过 PHP stripslashes() 函数)删除用户输入数据中的反斜杠(\)

    接下来我们创建一个检查函数(相比一遍遍地写代码,这样效率更好)。

    我们把函数命名为 test_input()。

    现在,我们能够通过 test_input() 函数检查每个 $_POST 变量,脚本是这样的:

    <!DOCTYPE HTML>
     <html>
     <head>
         <meta charset="utf-8">
         <title>PHP中文网(php.cn)</title>
     </head>
     <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>
         E-mail: <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;
     echo "<br>";
     echo $email;
     echo "<br>";
     echo $website;
     echo "<br>";
     echo $comment;
     echo "<br>";
     echo $gender;
     ?>
     
     </body>
    

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

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

    PHP 表单 - 必需字段
    <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>PHP中文网</title>
     </head>
     
     <style>
         .error {color: #FF0000;}
     </style>
     <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 (empty($_POST["email"])) {
             $emailErr = "电邮是必填的";
         } 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 = "性别是必选的";
         } 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;
     echo "<br>";
     echo $email;
     echo "<br>";
     echo $website;
     echo "<br>";
     echo $comment;
     echo "<br>";
     echo $gender;
     ?>
     
     </body>
     </html>
    

    PHP 表单 - 验证邮件和URL

    正则表达式

    正则表达式是一种描述一段文本规则的方法,它不是精确的匹配,而是通过一些特定的符号来模糊匹配

    在PHP中,我们使用preg_match函数来执行正则表达式的匹配,一个参数是我们的正则表达式规则,第二个参数是需要检查的文本

    preg_match ( string $正则 , string $字符串 [, array &$结果] )

    功能:根据$正则变量,匹配$字符串变量。如果存在则返回匹配的个数,把匹配到的结果放到$结果变量里。如果没有匹配到结果返回0。

    ^表示开始;$表示结束

    <?php
     header("Content-type:text/html;charset=utf-8");    //设置编码
     $str = 'date20150121';
     if (preg_match('/^date/', $str)) {
         echo '匹配成功';
     } else {
         echo '匹配失败';
     }
     ?>
    
    image.png

    preg_matchede第三个参数是匹配的内容,通常我们会将一个空的数组传递进去,因为是传址调用,匹配结束后,数组中会得到具体匹配的内容

    <?php
     header("Content-type:text/html;charset=utf-8");    //设置编码
     $str = 'date20150121';
     if (preg_match('/^date/', $str,$mat)) {
         print_r($mat);
     } else {
         echo '匹配失败';
     }
     ?>
    
    image.png

    在正则表达式中字母使用\w、而数字使用\d(\D表示非数字)来表示

    • + 表示一个或者多个

    • * 表示0个或者多个

    • ? 表示有或者没有

    • {n} 表示具体几位

    • {m, n} 表示大于m个,小于n个

    就像下面这样:

    <?php
     header("Content-type:text/html;charset=utf-8");    //设置编码
     $name = "zhang"; // wang zhu hu ma tan
     
     if (preg_match('/an|hu/', $name, $arr)) {
         print_r($arr);
     } else {
         echo '匹配失败';
     }
     ?>
    
    image.png

    使用或条件可以用来匹配字符串,如果仅仅是单个的字母或者字符,则可以使用范围表示

    使用[]可以表示一个字符的取值范围

    '/[a0.]/' 可以匹配包含了a或者0或者.的任意字符串

    另外,正则表达式还可以使用-来表示一组范围

    • [a-z] 表示小写的26个字母中的任意一个

    • [A-Z] 表示一个大写字母

    • [0-9] 表示一位十进制数

    PHP - 验证名称

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

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

    规则:邮箱名可以是字母、数字、下划线和点组成的任意字符;邮箱要包含@符号,后面的文字按域名规则处理

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

    $email = test_input($_POST["email"]);
    if (!preg_match("/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/",$email)) {
        $emailErr = "无效的 email 格式!";
    }
    
    PHP - 验证 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验证实例
    <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>PHP中文网</title>
     </head>
     
     <style>
         .error {color: #FF0000;}
     </style>
     <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("/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/",$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;
     echo "<br>";
     echo $email;
     echo "<br>";
     echo $website;
     echo "<br>";
     echo $comment;
     echo "<br>";
     echo $gender;
     ?>
     
     </body>
     </html>
    

    还能用正则表达式匹配手机号码哦,想想手机号码的验证?

    相关文章

      网友评论

        本文标题:PHP 表单验证

        本文链接:https://www.haomeiwen.com/subject/szepqftx.html