阻止垃圾郵件
一、垃圾郵件的預防技術
使用正則表達式或過濾器擴展驗證任何電子郵件地址
在表單值中監視這些字符。如果值中包含該列表中的任何內容,就不要使用那個值。
2.1 代碼:
email2.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Contact Me</title>
</head>
<body>
<h1>Contact Me</h1>
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
//函數功能是實現字符過濾
function spam_scrubber($value)
{
$very_bad = array('to', 'cc:', 'content-type:', 'mime-version:','multipart-mixed:','content-transfer-encoding');
//判斷$value中是否存在$very_bad中包含的各種變量
foreach($very_bad as $v)
{
if(stripos($value, $v) != false)
{
return '';
}
}
//字符串替換
$value = str_replace(array("\r", "\n", "%0a", "%0d" ), '', $value);
//過濾空格
return trim($value);
}
//將函數作用到數組的每個值上
$scrubbed = array_map('spam_scrubber', $_POST);
if(!empty($scrubbed['name']) && !($scrubbed['email']) && !empty($scrubbed['comments']))
{
$body = "Name: {$scrubbed['name']}\n\nComments: {$scrubbed['comments']}";
//字符截斷
$body = Wordwrap($body, 70);
mail('[email protected]', 'Contact From Submission', $body, "From:{$_POST['email']}");
echo '<p><em>Thank you for contacting me. I will reply some day.</em></p>';
$_POST =array() ; //將$_POST清空
}else{
echo '<p style="font-weight: bold; color: #C00"></p>';
}
}
?>
<p>Please fill out this form to contact me.</p>
<form action="email.php" method="post">
<p>Name: <input type="text" name="name" size="30" maxlength="60" value="<?php if(isset($_POST['name'])) echo $_POST['name']; ?>" /></p>
<p>Email Address: <input type="text" name="name" size="30" maxlength="80" value="<?php if(isset($_POST['email'])) echo $_POST['email']; ?>" /></p>
<p>Comments: <textarea name="comments" rows="5" cols="30"><?php if(isset($_POST['comments'])) echo $_POST['comments']; ?></textarea></p>
<p><input type="submit" name="submit" value="Send!" /></p>
</form>
</body>
</html>
2.2 函數解析:
stripos():函數查找字符串在另一字符串中第一次出現的位置(不區分大小寫)。
str_replace():函數以其他字符替換字符串中的一些字符(區分大小寫)。
array_map():將函數作用到數組中的每個值上,每個值都乘以本身,並返回帶有新值的數組。
2.3代碼解析:
$very_bad = array('to', 'cc:', 'content-type:', 'mime-version:','multipart-mixed:','content-transfer-encoding');
//判斷$value中是否存在$very_bad中包含的各種變量
foreach($very_bad as $v)
{
if(stripos($value, $v) != false)
{
return '';
}
}
解釋: $very_bad
存儲了所有可能的不合法聯繫人字符。foreach循環一次將訪問$very_bad
中的一個數據項,stripos()函數將檢查作爲$value
提供給該函數的數據項是否存在字符串中。一旦發現“危險”字符串,函數將返回一個空字符串並終止運行。
2.4 代碼運行:
注:由於提交的Email Address中出現了不合法字符,因此,該郵件不會被髮送。
通過類型驗證數據
一、2種驗證方法:
- 白名單:設置能通過的用戶,白名單以外的用戶都不能通過
- 黑名單:設置不能通過的用戶,黑名單以外的用戶都能通過。
1.1 代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Widget</title>
</head>
<body>
<?php # Script 13.2 - calculator.php
if($_SERVER['REQUEST_METHOD']=='POST')
{
$quantity = (int) $_POST['quantity'];
$price = (float) $_POST['price'];
$tax = (float) $_POST['tax'];
if(($quantity > 0) && ($price > 0) && ($tax > 0))
{
$total = $quantity * $price;
$total += $total * ($tax/100);
echo '<p>The cost of purchasing '.$quantity.' widget(s) at $'.number_format($price, 2).'each, plus tax, is $'.number_format($total, 2).'</p>';
}else{
echo '<p style = "font-weight: bold; color: #C00">Please enter a valid quantity, price, and tax rate.</p>';
}
}
?>
<h1>Widget Cost Calculator</h1>
<form action="calculator.php" method="post">
<p>Quantity: <input type="text" name="quantity" size="5" maxlength="10" value="<?php if(isset($quantity)) echo $quantity; ?>" /></p>
<p>Price: <input type="text" name="price" size="5" maxlength="10" value="<?php if(isset($price)) echo $price; ?>" /></p>
<p>Tax: <input type="text" name="tax" size="5" maxlength="10" value="<?php if(isset($tax)) echo $tax; ?>" /></p>
<p><input type="submit" name="submit" value="Calculate" /></p>
</form>
</body>
</html>
1.2 代碼解釋:
$quantity = (int) $_POST['quantity'];
$price = (float) $_POST['price'];
$tax = (float) $_POST['tax'];
解釋:通過強制轉換變量類型,驗證數據的正確格式
1.3 代碼運行:
按類型驗證文件
1、$_FILES['upload']['type']
是指上傳瀏覽器提供的MIME類型。但是惡意用戶很容易通過提供虛假的MIME類型誘騙瀏覽器
2、Fileinfo是在服務器端進行內容類型的檢驗。Fileinof通過獲取文件的“魔法字節”或“魔法數字”來判斷文件的類型(和編碼),例如,構成GIF圖片的數據必須以ASCII碼GIF89a或GIF87a開頭,構成PDF文件的數據必須以%PDF開頭。
3、如何使用Fileinfo:
要使用Fileinfo,首先創建Fileinfo資源:
$fileinfo = finfo_open(kind)
kind值是個常量,指定創建的資源類型,判斷文件類型的常量是FILEINFO_MIME_TYPE,即$file = finfo_open(FILEINFO_MYIME_TYPE)
接下來,調用finfo_file()函數,提供Fileinfo資源和要檢查的文件的引用
finfo_file($fileinfo, $filename)
此函數基於文件的實際“魔法字節”,返回文件的MIME類型(已經創建的資源)完成後,應關閉Fileinfo的資源
finfo_close($fileindo)
4、代碼upload_rtf.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload a RTF Document</title>
</head>
<body>
<?php # Script 13.3 - upload_rtf.php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
if(isset($_FILES['upload']) && file_exists($_FILES['upload']['tmp_name']))
{
//創建fileinfo資源
$fileinfo = finfo_open(FILEINFO_MIME_TYPE);
//服務器端檢查文件類型
if(finfo_file($fileinfo, $_FILES['upload']['tmp_name']) == 'text/rtf')
{
echo '<p><em>The file would be acceptable</em></p>';
//刪除臨時文件
unlink($_FILE['upload']['tmp_name']);
}else{
echo '<p style = "font-weight: bold; color: #C00">Please upload an RTF document.</p>';
}
//關閉Fileinfo資源
finfo_close($fileinfo);
}
}
?>
<form enctype="multipart/form-data" action="upload_rtf.php" method = "post">
<input type="hidden" name="MAX_FILE_SIZE" value="524288" />
<fieldset>
<legend>Select an RTF document of 512KB or smaller to be uploaded</legend>
<p><b>File:</b> <input type="file" name="upload"/></p>
<div align="center"><input type="submit" name="submit" value="Submit"></div>
</fieldset>
</form>
</body>
</html>
阻止XSS攻擊
1、XSS(跨站腳本)攻擊——
許多動態驅動的web應用程序會獲取用戶提交的信息,將其存儲在數據庫中,然後在另一個頁面上重新顯示該信息。當用戶在數據中輸入HTML代碼,這種代碼就可能拋棄站點的佈局和美感。更糟糕的是,JS也只是純文本,但它是Web瀏覽器內可執行的腳本,可能會造成彈窗,竊取cookie或者把瀏覽器重定向到其他站點,稱之爲XSS攻擊。
2、代碼:
xss.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>XSS Attacks</title>
</head>
<body>
<?php # Script 13.4 - xss.php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
echo "<h2>Original</h2><p>{$_POST['data']}</p>";
echo '<h2>After htmlspecialchars() </h2><p>'.htmlspecialchars($_POST['data']).'</p>';
echo '<h2>After htmlentities() </h2><p>'.htmlentities($_POST['data']).'</p>';
echo "<h2>After strip_tags() </h2><p>".strip_tags($_POST['data'])."</p>";
}
?>
<form action="xss.php" method="post">
<p>Do your worst!<textarea name="data" cols="40" rows="4"></textarea><div><input type="submit" name="submit" value="Submit" /></div>
</p>
</form>
</body>
</html>
3、函數解析:
htmlspecialchars():把預定義的字符轉換爲 HTML 實體
htmlentities():把字符轉換爲 HTML 實體
strip_tags():去掉字符串中的 HTML 標籤
這3個函數以從破壞性最小到最大的順序列出。
4、代碼運行:
使用過濾器擴展
1、過濾器擴展的目的——驗證數據或清理數據
2、使用函數filter_var(variable, filter[,options])
3、過濾器選擇
4、代碼:
calculator2.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Widget</title>
</head>
<body>
<?php # Script 13.2 - calculator.php
if($_SERVER['REQUEST_METHOD']=='POST')
{
//$quantity = (int) $_POST['quantity'];
//$price = (float) $_POST['price'];
//$tax = (float) $_POST['tax'];
//如果是整數則保存,否則爲null
$quantity = (isset($_POST['quantity'])) ? filter_var($_POST['quantity'], FILTER_VALIDATE_INT, array('min_range'=>1)) : NULL;
//如果是浮點數,則保存,否則爲null
$price = (isset($_POST['price'])) ? filter_var($_POST['price'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) : NULL;
$tax = (isset($_POST['tax'])) ? filter_var($_POST['tax'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) : NULL;
if(($quantity > 0) && ($price > 0) && ($tax >
0))
{
$total = $quantity * $price;
$total += $total * ($tax/100);
echo '<p>The cost of purchasing '.$quantity.' widget(s) at $'.number_format($price, 2).'each, plus tax, is $'.number_format($total, 2).'</p>';
}else{
echo '<p style = "font-weight: bold; color: #C00">Please enter a valid quantity, price, and tax rate.</p>';
}
}
?>
<h1>Widget Cost Calculator</h1>
<form action="calculator2.php" method="post">
<p>Quantity: <input type="text" name="quantity" size="5" maxlength="10" value="<?php if(isset($quantity)) echo $quantity; ?>" /></p>
<p>Price: <input type="text" name="price" size="5" maxlength="10" value="<?php if(isset($price)) echo $price; ?>" /></p>
<p>Tax: <input type="text" name="tax" size="5" maxlength="10" value="<?php if(isset($tax)) echo $tax; ?>" /></p>
<p><input type="submit" name="submit" value="Calculate" /></p>
</form>
</body>
</html>
5、代碼運行
預防SQL注入攻擊
1、SQL注入攻擊——是指企圖把不良代碼插入到站點SQL查詢中。這類攻擊的目標之一是,它們將創建一個語法上無效的查詢,從而再得到的出錯消息中呈現關於腳本或數據庫的某些消息。而注入攻擊更大的目的是改變、破壞或暴露存儲的數據。
2、預處理語句的性能
預處理語句比老式的查詢方式更安全,而且可能也會更快。如果一個PHP腳本多次發送相同的PHP查詢到MySQL,每次使用不同的值,預處理可以加快速度。在這種情況下,只會把查詢本身發送給MySQL,並且只會解析一次。然後,單獨把值發送給MySQL。
3、如果不使用預處理語句,整個查詢(包括SQL語法和具體的值)都會作爲一個長字符串發送到MySQL。然後MySQL分析並執行它。使用預處理查詢,SQL語法首先被髮送到MySQL解析,確保它在語法上是有效的,然後單獨發送特定的值,MySQL使用這些值組合查詢,然後執行它。
4、預處理的優點:它可以帶來更高的安全性、並且可能提供更好的工作的性能。
5、代碼:
post_message.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Post a message</title>
</head>
<body>
<?php # Script 13.6 - post_message.php
if($_SERVER['REQUEST_METHOD'] == 'POST')
{
$mysqli = mysqli_connect('localhost', 'root', '1111', 'forum');
$sql = "INSERT INTO messages(forum_id, parent_id, user_id, subject, body, date_entered) VALUES (?,?,?,?,?, NOW())";
$stmt = mysqli_prepare($mysqli, $sql);
mysqli_stmt_bind_param($stmt, 'iiiss', $forum_id, $parent_id, $user_id, $subject, $body);
$forum_id = (int) $_POST['forum_id'];
$parent_id = (int) $_POST['parent_id'];
$user_id = 3;
$subject = strip_tags($_POST['subject']);
$body = strip_tags($_POST['body']);
mysqli_stmt_execute($stmt);
if(mysqli_stmt_affected_rows($stmt) == 1){
echo '<p>Your messages has been posted.</p>';
}else{
echo '<p style="font-weight: bold; color: #C00">Your message could not be posted.</p>';
echo '<p>'.mysqli_stmt_error($stmt).'</p>';
}
mysqli_stmt_close($stmt);
mysqli_close($mysqli);
}
?>
<form action="post_message.php" method="post">
<fieldset>
<legend>Post a message</legend>
<p><b>Subject</b>: <input type="text" name="subject" size="30" maxlength="100" /></p>
<p><b>Body</b>: <textarea name="body" cols="40" rows="4"></textarea></p>
<div align="center"><input type="submit" name="submit" value="Submit"></div>
</fieldset>
<input type="hidden" name="forum_id" value="1" />
<input type="hidden" name="parent_id" value="0" />
</form>
</body>
</html>
6、代碼解析:
$sql = "INSERT INTO messages(forum_id, parent_id, user_id, subject, body, date_entered) VALUES (?,?,?,?,?, NOW())"; //預處理sql語句
$stmt = mysqli_prepare($mysqli, $sql); //將結果寫入到對應的數據庫變量中
mysqli_stmt_bind_param($stmt, 'iiiss', $forum_id, $parent_id, $user_id, $subject, $body); //綁定對應的參數,‘iiiss’表示第1,2, 3是整數 第4,5是字符串等類型
mysqli_stmt_execute($stmt);//執行預處理語句
mysqli_stmt_close($stmt);//關閉預處理資源
7、代碼運行