PHP學習練手(十五)


阻止垃圾郵件


一、垃圾郵件的預防技術

  1. 使用正則表達式或過濾器擴展驗證任何電子郵件地址

  2. 在表單值中監視這些字符。如果值中包含該列表中的任何內容,就不要使用那個值。
    這裏寫圖片描述

    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、代碼運行
這裏寫圖片描述

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章