1. 程式人生 > >PHP學習練手(十五)

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、程式碼執行
這裡寫圖片描述

這裡寫圖片描述