PHP 表單驗證
本章及後續章節將展示如何使用 PHP 驗證表單資料。
PHP 表單驗證
處理 PHP 表單時請考慮安全性!
這些頁面將展示如何安全地處理 PHP 表單。正確驗證表單資料對於保護您的表單免受駭客和垃圾郵件傳送者的侵害至關重要!
本章中我們將使用的 HTML 表單包含各種輸入欄位:必填和選填的文字欄位、單選按鈕以及一個提交按鈕。
上述表單的驗證規則如下:
欄位 | 驗證規則 |
---|---|
名稱 | 必填。+ 只能包含字母和空格 |
電子郵件 | 必填。+ 必須包含有效的電子郵件地址(帶 @ 和 .) |
網站 | 選填。如果存在,則必須包含有效的 URL |
註釋 | 選填。多行輸入欄位(textarea) |
性別 | 必填。必須選擇一項 |
首先,我們來看錶單的純 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
<input type="radio" name="gender" value="other">Other
表單元素
表單的 HTML 程式碼如下:
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
當表單提交時,表單資料將透過 method="post" 傳送。
什麼是 $_SERVER["PHP_SELF"]
變數?$_SERVER["PHP_SELF"]
是一個超全域性變數,它返回當前執行指令碼的檔名。
因此,$_SERVER["PHP_SELF"]
將提交的表單資料傳送到指令碼本身,而不是跳轉到另一個頁面。這樣,使用者將在同一頁面上收到錯誤訊息。
什麼是 htmlspecialchars()
函式?htmlspecialchars()
函式將特殊字元轉換為 HTML 實體。這意味著它會將 `<` 和 `>` 等 HTML 字元替換為 `<` 和 `>`。這可以防止攻擊者透過在表單中注入 HTML 或 Javascript 程式碼(跨站指令碼攻擊)來利用程式碼。
警告!
$_SERVER["PHP_SELF"]
變數可能被駭客利用!
如果在頁面中使用 PHP_SELF,使用者就可以輸入斜槓 `/`,然後是一些跨站指令碼(XSS)命令來執行。
跨站指令碼(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>
這段程式碼添加了一個指令碼標籤和一個 alert 命令。當頁面載入時,JavaScript 程式碼將被執行(使用者將看到一個 alert 框)。這只是一個簡單無害的示例,說明了 PHP_SELF 變數可能被利用的方式。
請注意,任何 JavaScript 程式碼都可以新增到 <script> 標籤中!駭客可以重定向使用者到一個另一個伺服器上的檔案,而該檔案可能包含惡意程式碼,可以更改全域性變數或將表單提交到另一個地址以儲存使用者資料,例如。
如何避免 $_SERVER["PHP_SELF"] 漏洞?
可以使用 htmlspecialchars()
函式來避免 $_SERVER["PHP_SELF"]
漏洞。
表單程式碼應如下所示:
<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>
—— 這將不會被執行,因為它將被儲存為 HTML 轉義的程式碼,如下所示:
<script>location.href('http://www.hacked.com')</script>
現在,程式碼可以安全地顯示在頁面上或嵌入到電子郵件中。
當用戶提交表單時,我們還將執行另外兩項操作:
- 從使用者輸入資料中刪除不必要的字元(額外空格、製表符、換行符)(使用 PHP 的
trim()
函式) - 從使用者輸入資料中刪除反斜槓 `\`(使用 PHP 的
stripslashes()
函式)
下一步是建立一個函式來為我們完成所有檢查(這比一遍又一遍地編寫相同的程式碼要方便得多)。
我們將該函式命名為 test_input()
。
現在,我們可以使用 test_input()
函式檢查每個 $_POST
變數,指令碼如下:
示例
// define variables and set to empty values
$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
,則表示表單已提交——應進行驗證。如果尚未提交,則跳過驗證並顯示一個空白表單。
然而,在上面的示例中,所有輸入欄位都是可選的。即使使用者不輸入任何資料,指令碼也能正常工作。
下一步是使輸入欄位成為必填項,並在需要時建立錯誤訊息。