PHP学习笔记-Session
轉載請標明出處:
http://blog.csdn.net/hai_qing_xu_kong/article/details/52262182
本文出自:【顧林海的博客】
前言
上一篇講述了Cookie管理,我們知道Cookie是服務器留在用戶計算機中的小文件。每當相同的計算機通過瀏覽器請求頁面時,它同時會發送 cookie。并且數
據信息是以明文文本的形式保存在客戶端計算機中,因此最好不要保存一些含有敏感的、未加密的數據,否則會影響網絡的安全性。
對比Cookie,Session會話文件中保存的數據在PHP腳本中是以變量的形式創建的,創建的會話變量在生命周期中可以被跨頁的請求所引用。另外,Session會話是存儲在服務器端的,相對安全,并且不像Cookie那樣有存儲長度的限制。
Session使用前的準備
在進行Session使用前,我們需要知道什么是Session、原理以及它的功能。
什么是Session
Session譯為“會話”,其本義是指有始有終的一系列動作/消息,如打電話時從拿起電話撥號到掛斷電話這一系列過程可以稱為一個Session。
在計算機專業術語中,Session是指一個終端用戶與交互系統進行通信的時間間隔,通常指從注冊進入系統到注銷退出系統所經過的時間。因此,Session實際上是一個特定的時間概念。
工作原理
當啟動一個Session會話時,會生成一個隨機且唯一的session_id,也就是Session的文件名,此時session_id存儲在服務器的內存中,當關閉頁面時此id會自動注銷,重新登錄此頁面,會再次生成一個隨機且唯一的id。
Session的功能
Session在Web技術中非常重要。由于網頁是一種無狀態的連接程序,因此無法得知用戶的瀏覽狀態。通過Session則可記錄用戶相關信息,以供用戶再次以此身份對Web服務器提交要求時作確認。例如,在電子商務網站中,通過Session記錄用戶登錄的信息,以及用戶所購買的商品,如果沒有Session,那么用戶每進入一個頁面都需要登錄一次用戶名和密碼。
另外,Session會話適用于存儲信息量比較少的情況。如果用戶需要存儲的信息量相對較少,并且對存儲內容不需要長期存儲,那么使用Session把信息存儲到服務器端比較合適。
Session的使用
創建一個Session需要以下幾個步驟:
1、啟動會話的方式有兩種,一種是使用session_start()函數,另一種方式是使用session_register()函數為會話創建一個變量來隱含地啟動會話。
session_start()函數在頁面開始位置調用,然后會話變量被登錄到數據$_SESSION。
通過session_register()函數用來為會話創建一個變量來隱含地啟動會話,但要求設置php.ini文件的選項,即將register_globals指令設置為on,然后重新啟動Apache服務器即可;使用session_register()函數時不需要調用session_start()函數,PHP會在創建變量之后隱含地調用session_start()函數。
2、會話變量被創建后,全部保存在數組SESSION中。通過數組_SESSION創建一個會話變量很容易,只要直接給該數組添加一個元素即可。
<?php /*** Created by IntelliJ IDEA.* User: 蛋蛋球* Date: 2016/8/20* Time: 14:41*/session_start(); $_SESSION["admin"]=null;?>上述程序中第一行代碼是用于啟動Session,第二行代碼是聲明一個名為admin的變量,并賦空值。
3、使用會話時,我們需要判斷會話變量是否有一個會話ID存在,如果不存在,就需要創建一個,并且使其能夠通過全局數組$_SESSION進行訪問;如果已經存在,則將這個已經創建的會話變量載入以供用戶使用。
<?php if(!empty($_SESSION['session_name'])){$myvalue=$_SESSION['session_name']; } ?>就像上述程序,先判斷用于存儲用戶名的Session會話變量是否為空,不為空時,將會話變量賦給一個變量$myvalue。
4、刪除會話的方法主要有刪除單個會話、刪除多個會話和結束當前會話3種,下面分別介紹這三種。
(1)刪除單個會話即刪除單個會話變量,同數組的操作一樣,直接注銷$_SESSION數組的某個元素即可。
<?php unset($_SESSION['user']); ?>使用unset()函數時,要注意$_SESSION數組中元素不能省略,即不可以一次注銷整個數組,這樣會禁止整個會話的功能,如unset($_SESSION)函數會將全局變量$_SESSION銷毀,而且沒有辦法將其恢復,用戶也不能再注冊$_SESSION變量。如果要刪除多個或全部會話,可采用下面的兩種方法。
(2)刪除多個會話即一次注銷所有的會話變量,可以通過將一個空的數組賦值給$_SESSION來實現。
<?php $_SESSION=array(); ?>(3)如果整個會話已經結束,首先應該注銷所有的會話變量,然后使用session_destroy()函數清除結束當前的會話,并清空會話中的所有資源,徹底銷毀Session。
<?php session_destroy(); ?>給Session設置時間
Session失效時間設置主要有兩種方式:
1、客戶端沒有禁止Cookie
(1)使用session_set_cookie_params()設置Session的失效時間,此函數時Session結合Cookie設置失效時間。以下示例讓Session在1分鐘后失效:
<?php $time=1*60; session_set_cookie_params($time); session_start(); $_SESSION[username]='mr'; ?>session_set_cookie_params()必須在session_start之前調用。
不推薦使用此函數,此函數在一些瀏覽器上會出現問題,所有一般手動設置失效時間。
(2)使用setcookie()函數對Session設置失效時間,如讓Session在1分鐘后失效:
<?php session_start(); $time=1*60; setcookie(session_name(),session_id(),time()+$time,"/"); $_SESSION['user']="mr"; ?>在上面程序的setcookie()函數中,session_name是Session的名稱,session_id是判斷客戶端用戶的標示,因為session_id是隨機產生的唯一名稱,所以Session是相對安全的。失效時間和Cookie的失效時間一樣,最后一個參數為可選參數,是放置Cookie的路徑。
2、客戶端禁止Cookie
當客戶端禁用Cookie時,Session頁面間傳遞會失效,可以將客戶端禁止Cookie想象成一家大型連鎖超市,如果在其中一家超市內辦理了會員卡,但是超市之間并沒有聯網,那么會員卡就只能在辦理的那家超市使用。解決這個問題有4種方法:
(1)在登錄之前提醒用戶必須打開Cookie,這是很多論壇的做法。
(2)設置php.ini文件中的session.use_trans_sid = 1,或者編譯時打開-enable-trans-sid選項,讓PHP自動跨頁面傳遞session_id。
(3)通過GET方法,隱藏表單傳遞session_id。
(4)使用文件或者數據庫存儲session_id,在頁面間傳遞中手動調用。
以上2種方法不做詳細講解,因為用戶不能修改服務器的php.ini文件。第3種方法我們就不可以使用Cookie設置失效時間,但是登陸情況沒有變化。
我們基于第3種方法使用GET方法傳輸,先看實際效果圖:
<?php header("Content-Type:text/html;charset=utf-8"); session_start(); ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd";> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>登錄頁面</title> <link href="css/style.css" rel="stylesheet" type="text/css" /> </head><body> <table width="328" border="0" align="center" cellpadding="0" cellspacing="0"><tr><td height="100"></td></tr><tr><td height="214" valign="top" background="images/index_01.jpg"><form id="form1" name="form1" method="post" action="common.php?<?=session_name(); ?>=<?=session_id(); ?>"><table width="100%" height="171" border="0" cellpadding="0" cellspacing="0"><tr><td width="200" height="60"></td><td> </td></tr><tr><td align="right" class="white12">用戶名:</td><td><input name="username" type="text" size="15" /> </td></tr><tr><td align="right" class="white12">密 碼:</td><td><input name="password" type="password" size="15" /></td></tr><tr><td> </td><td valign="bottom"><input type="submit" name="Submit" value="登 錄" /><input type="reset" name="Submit2" value="取 消" /></td></tr></table></form></td></tr> </table> </body> </html>上面是我們的登陸主界面的代碼。在最上面執行了session_start();
這時會話變量被登錄到數據$_SESSION。
看到點擊登陸是地址欄會顯示session的ID,并在當前目錄下的tmp文件夾下生產一個以sess_開頭加上sessionID的文件,查看文件內容可以發現存儲著以下值:
admin|s:6:”mrsoft”;
這時點擊登陸執行以下代碼:
<form id="form1" name="form1" method="post" action="common.php?<?=session_name(); ?>=<?=session_id(); ?>">點擊登陸按鈕后執行common.php腳本,繼續查看common.php:
<?php header("Content-Type:text/html;charset=utf-8"); error_reporting(0); $path = './tmp/'; $sess_name = session_name(); $sess_id = $_GET[$sess_name]; session_id($sess_id); session_save_path($path); session_start(); if ((trim($_POST['username'])) != 'tm' or (trim($_POST['password']) != '111')) {echo "<script>alert('用戶名與密碼錯誤!');location.href='index.php'</script>"; } $_SESSION['admin'] = 'mrsoft'; ?> <link href="css/style.css" rel="stylesheet" type="text/css" /><table width="328" border="0" align="center" cellpadding="0" cellspacing="0"><tr><td height="100"></td></tr><tr><td height="214" valign="top" background="images/index_01.jpg"><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td width="100"></td><td height="70"></td></tr><tr><td align="center" valign="middle"> </td><td height="80" align="center" valign="middle"><p class="white12"> 恭喜您登錄成功<a href="connect.php?<?=session_name(); ?>=<?=session_id() ?>"> 請點擊轉入內容頁面</a></p></td></tr></table></td></tr> </table>代碼比較簡單,先是獲取session的名稱,然后根據session名稱獲取session的ID,然后通過session_id()函數存取目前 session的ID,并保存在當前路徑下的tmp文件夾下。最后通過$_SESSION[‘admin’] = ‘mrsoft’;將mrsoft值保存在服務器中以便你其他模塊操作的使用 。
假設我們將tmp文件夾下的生成的文件刪除,點擊登陸按鈕執行以下代碼:
<form id="form1" name="form1" method="post" action="connect.php?<?=session_name(); ?>=<?=session_id(); ?>"> <?php header("Content-Type:text/html;charset=utf-8"); error_reporting(0); $sess_name = session_name(); $sess_id = $_GET[$sess_name]; session_id($sess_id); session_save_path('./tmp/'); session_start(); if ($_SESSION['admin'] == "") {echo "<script>alert('對不起,你沒有權限');location.href='index.php'</script>"; } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>后臺管理頁面</title> <link href="css/style.css" rel="stylesheet" type="text/css" /> </head><body> <table width="779" height="712" border="0" align="center" cellpadding="0" cellspacing="0" background="images/index_02.jpg"><tr><td></td></tr> </table> </body> </html>從上面程序可以看出來登陸時會去檢查session的ID生成的文件中是否有admin,為空時,說明沒有權限,當然之前tmp文件下的文件如果不刪除的話,可以直接登陸進入,無需用戶名和密碼。
Session高級應用
session的臨時文件
在服務器中,如果將所有用戶的Session都保存到臨時目錄中,會降低服務器的安全性和效率,打開服務器存儲的站點會非常慢。使用PHP函數session_save_path()存儲Session臨時文件,可緩解因臨時文件的存儲導致服務器效率降低和站點打開緩慢的問題。
<?php $path = './tmp/'; // 設置session存儲路徑 session_save_path($path); session_start(); // 初始化session $_SESSION[username] = true; echo "Session文件名稱為:sess_" , session_id(); ?>session緩存
Session的緩存是將網頁中的內容臨時存儲到IE客戶端的Temporary Internet Files文件夾下,并且可以設置緩存的時間。當第一次瀏覽網頁后,頁面的部分內容在規定的時間內就被臨時存儲在客戶端的臨時文件夾中,這樣在下次訪問這個頁面時,就可以直接讀取緩存中的內容,從而提高網站的瀏覽效率。
Session緩存的完成使用的是session_cache_limiter()函數,其語法如下:
string session_cache_limiter ( [string cache_limiter])參數cache_limiter為public或private。同時Session緩存并不是指在服務器端而是客戶端緩存,在服務器中沒有顯示。
緩存時間的設置,使用的是session_cache_expire()函數,其語法如下:
int session_cache_expire ( [int new_cache_expire])參數cache_expire是Session緩存的時間數字,單位是分鐘。
下面是Session緩存頁面過程:
<?php session_cache_limiter('private'); $cache_limit = session_cache_limiter();session_cache_expire(30); $cache_expire = session_cache_expire();session_start(); ?> <html> <head> <title>Session客戶端緩存</title> </head> <style type="text/css"> <!-- .black12 {font-family: "宋體";font-size: 12px;line-height: 30px;color: #000000;text-decoration: none; } .red12 {font-family: "宋體";font-size: 12px;line-height: 30px;color: red;text-decoration: none; } --> </style><body> <table width="502" height="300" border="0" align="center" cellpadding="0" cellspacing="0" background="images/index_01.jpg"><tr><td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td height="120"> </td></tr><tr><td align="center" class="black12">緩存限制為 <span class="red12"><?=$cache_limit ?></span></td></tr><tr><td align="center" class="black12">緩存Session頁面失效時間在 <span class="red12"><?=$cache_expire ?></span> 分鐘之后</td></tr></table></td></tr> </table> </body> </html>Session數據庫存儲
通過改變Session存儲文件夾使Session不至于將臨時文件夾填滿而造成站點癱瘓,但一個網站一天登陸幾千人,一個月就上萬人,這時站點中就存在這么多Session文件,要在這些文件中查詢某個session_id也不是一件輕松的事情。這時就可以用Session數據庫存儲,也就是PHP中的session_set_save_handler()函數。
語法格式如下:
bool session_set_save_handler ( string open, string close, string read, string write, string destroy, string gc)| open(save_path,session_name) | 找到Session存儲地址,取出變量名稱 |
| close() | 不需要參數,關閉數據庫 |
| read(key) | 讀取Session鍵值,key對應session_id |
| write(key,data) | 其中data對應設置的Session變量 |
| destroy(key) | 注銷Session對應Session鍵值 |
| gc(expiry_time) | 清除過期Session記錄 |
一般應用參數直接使用變量,但是此函數中參數為6個函數,而且在調用時只是調用函數名稱的字符串,下面將分別講解這6個參數(函數),最后將把這些封裝進類中。
(1)封裝session_open()函數,連接數據庫,代碼如下:
function _session_open($save_path,$session_name) {global $handle;$handle = mysql_connect('localhost','root','root') or die('數據庫連接失敗'); //連接MySQL數據庫mysql_select_db('db_database11',$handle) or die('數據庫中沒有此庫名'); //找到數據庫return(true); }2)封裝session_close()函數,關閉數據庫連接,代碼如下:
function _session_close() {global $handle;mysql_close($handle);return(true); }在這個參數中不需要任何參數,所以不論是Session存儲到數據庫還是文件中,只需返回true即可。但是如果是MySQL數據庫,最好是將數據庫關閉,以保證以后不會出現麻煩。
(3)封裝session_read()函數,在函數中設定當前時間的UNIX時間戳,根據$key值查找Session名稱及內容,代碼如下:
function _session_read($key) {global $handle; //全局變量$handle連接數據庫$time = time(); //設定當前時間 $sql = "select session_data from tb_session where session_key = '$key' and session_time > $time";$result = mysql_query($sql,$handle);$row = mysql_fetch_array($result);if ($row){return($row['session_data']); //返回Session名稱及內容}else{return(false);} }存儲進數據庫中的session_expiry是UNIX時間戳。
(4)封裝session_write()函數,函數中設定Session失效時間,查找到Session名稱及內容,如果查詢結果為空,則將頁面中Session根據session_id、session_name、失效時間插入數據庫中;如果查詢結果不為空,則根據$key修改數據庫中Session存儲信息,返回執行結果,代碼如下:
function _session_write($key,$data) {global $handle;$time = 60*60; //設置失效時間$lapse_time = time() + $time; //得到UNIX時間戳 $sql = "select session_data from tb_session where session_key = '$key' and session_time > $lapse_time";$result = mysql_query($sql,$handle);if (mysql_num_rows($result) == 0 ) { //沒有結果$sql = "insert into tb_session values('$key','$data',$lapse_time)";//插入數據庫sql語句$result = mysql_query($sql,$handle);}else{$sql = "update tb_session set session_key = '$key',session_data = '$data',session_time = $lapse_time where session_key = '$key'"; //修改數據庫sql語句 $result = mysql_query($sql,$handle);}return($result); }(5)封裝session_destroy()函數,根據$key值將數據庫中Session刪除,代碼如下:
function _session_destroy($key) {global $handle;$sql = "delete from tb_session where session_key = '$key'"; //刪除數據庫sql語句$result = mysql_query($sql,$handle);return($result); }(6)封裝session_gc()函數,根據給出的失效時間刪除過期Session,代碼如下:
function _session_gc($expiry_time) {global $handle;$lapse_time = time(); //將參數$expiry_time賦值為當前時間戳$sql = "delete from tb_session where expiry_time < $lapse_time"; //刪除數據庫sql語句$result = mysql_query($sql,$handle);return($result); }以上為session_set_save_handler()函數的6個參數(函數)。
至此關于PHP的Session講解完畢。
總結
以上是生活随笔為你收集整理的PHP学习笔记-Session的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 那些你投的基金没告诉你的事
- 下一篇: php对接linepay支付