深入講解PHP Session及如何保持其不過(guò)期的方法
SESSION的實(shí)現(xiàn)中采用COOKIE技術(shù),SESSION會(huì)在客戶端保存一個(gè)包含session_id(SESSION編號(hào))的COOKIE;在服務(wù)器端保存其他session變量,比如session_name等等。當(dāng)用戶請(qǐng)求服務(wù)器時(shí)也把session_id一起發(fā)送到服務(wù)器,通過(guò) session_id提取所保存在服務(wù)器端的變量,就能識(shí)別用戶是誰(shuí)了。同時(shí)也不難理解為什么SESSION有時(shí)會(huì)失效了。
當(dāng)客戶端禁用COOKIE時(shí)(點(diǎn)擊IE中的“工具”—“Internet選項(xiàng)”,在彈出的對(duì)話框里點(diǎn)擊“安全”—“自定義級(jí)別”項(xiàng),將“允許每個(gè)對(duì)話COOKIE”設(shè)為禁用),session_id將無(wú)法傳遞,此時(shí) SESSION失效。不過(guò)php5在linux/unix平臺(tái)可以自動(dòng)檢查cookie狀態(tài),如果客戶端設(shè)置了禁用,則系統(tǒng)自動(dòng)把session_id附加到url上傳遞。windows主機(jī)則無(wú)此功能。
Session常見(jiàn)函數(shù)及用法?
Session_start() :開(kāi)始一個(gè)會(huì)話或者返回已經(jīng)存在的會(huì)話。
說(shuō)明:這個(gè)函數(shù)沒(méi)有參數(shù),且返回值均為true。如果你使用基于cookie的session(cookie-based sessions),那么在使用Session_start()之前瀏覽器不能有任何輸出,否則會(huì)發(fā)生以下錯(cuò)誤:
Warning: Cannot send session cache limiter - headers already sent (output started at /usr/local/apache/htdocs/cga/member/1.php:2)…………
你可以在php.ini里啟動(dòng)session.auto_start=1,這樣就無(wú)需每次使用session之前都要調(diào)用session_start()。但啟用該選項(xiàng)也有一些限制,如果確實(shí)啟用了 session.auto_start,則不能將對(duì)象放入會(huì)話中,因?yàn)轭惗x必須在啟動(dòng)會(huì)話之前加載以在會(huì)話中重建對(duì)象。
請(qǐng)求結(jié)束后所有注冊(cè)的變量都會(huì)被序列化。已注冊(cè)但未定義的變量被標(biāo)記為未定義。在之后的訪問(wèn)中這些變量也未被會(huì)話模塊定義,除非用戶以后定義它們。
警告: 有些類型的數(shù)據(jù)不能被序列化因此也就不能保存在會(huì)話中。包括 resource 變量或者有循環(huán)引用的對(duì)象(即某對(duì)象將一個(gè)指向自己的引用傳遞給另一個(gè)對(duì)象)。
注冊(cè)SESSION變量 :
PHP5使用$_SESSION[‘xxx']=xxx注冊(cè)SESSION全局變量。和GET,POST,COOKIE的使用方法相似。
注意:session_register(),session_unregister ,session_is_registered在php5下不再使用,除非在php.ini里把register_globle設(shè)為on,不過(guò)出于安全考慮,強(qiáng)烈建議關(guān)閉register_globle。HTTP_SESSION_VARS也不提倡使用了,官方建議用$_SESSION代替之。例如:
Page1.php
<?php Session_start(); //使用SESSION前必須調(diào)用該函數(shù)。 $_SESSION[‘name']=”我是黑旋風(fēng)李逵!”; //注冊(cè)一個(gè)SESSION變量 $_SESSION[‘passwd']=”mynameislikui”; $_SESSION[‘time']=time(); echo ' 通過(guò)COOKIE傳遞SESSION'; //如果客戶端支持cookie,可通過(guò)該鏈接傳遞session到下一頁(yè)。 echo ' . SID . '">通過(guò)URL傳遞SESSION';//客戶端不支持cookie時(shí),使用該辦法傳遞session. ?>
Page2.php
<?php session_start(); echo $_SESSION['name']; // echo $_SESSION['passwd']; // echo date('Y m d H:i:s', $_SESSION['time']); echo ' 返回山一頁(yè)'; ?>
有兩種方法傳遞一個(gè)會(huì)話 ID:
- cookie
- URL 參數(shù)
會(huì)話模塊支持這兩種方法。cookie 更優(yōu)化,但由于不總是可用,也提供替代的方法。第二種方法直接將會(huì)話 ID 嵌入到 URL 中間去。
PHP 可以透明地轉(zhuǎn)換連接。除非是使用 PHP 4.2 或更新版本,需要手工在編譯 PHP 時(shí)激活。在 Unix 下,用 --enable-trans-sid 配置選項(xiàng)。如果此配置選項(xiàng)和運(yùn)行時(shí)選項(xiàng) session.use_trans_sid 都被激活(修改php.ini),相對(duì) URI 將被自動(dòng)修改為包含會(huì)話 ID。
session_id
session_id() 用于設(shè)定或取得當(dāng)前session_id。php5中既可以使用session_id(),也可以通過(guò)附加在url上的SID取得當(dāng)前會(huì)話的session_id和session_name。
如果session_id()有具體指定值的話,將取代當(dāng)前的session_id值。使用該函數(shù)前必須啟動(dòng)會(huì)話:session_start();
當(dāng)我們使用session cookies時(shí),如果指定了一個(gè)session_id()值,每次啟動(dòng)session_start()都會(huì)往客戶端發(fā)送一個(gè)cookie值。不論當(dāng)前session_id是否與指定值相等。
session_id()如果沒(méi)有指定值,則返回當(dāng)前session_id();當(dāng)前會(huì)話沒(méi)有啟動(dòng)的話,則返回空字符串。
檢查session是否存在?
在以往的php版本中通常使用session_is_register()檢查session是否存在,如果您使用$_SESSION[‘XXX']=XXX來(lái)注冊(cè)會(huì)話變量,則session_is_register()函數(shù)不再起作用。你可以使用
isset($_SESSION[‘xxx'])來(lái)替代。
更改session_id session_regenerate_id() 更改成功則返回true,失敗則返回false。
使用該函數(shù)可以為當(dāng)前session更改session_id,但不改變當(dāng)前session的其他信息。例如:
<?php session_start(); $old_sessionid = session_id(); session_regenerate_id(); $new_sessionid = session_id(); echo "原始 SessionID: $old_sessionid "; echo "新的 SessionID: $new_sessionid "; echo" "; print_r($_SESSION); echo""; ?>
session_name() 返回當(dāng)前session的name或改變當(dāng)前session的name。如果要改變當(dāng)前session的name,必須在session_start() 之前調(diào)用該函數(shù)。注意:session_name不能只由數(shù)字組成,它至少包含一個(gè)字母。否則會(huì)在每時(shí)每刻都生成一個(gè)新的session id.
session改名示例:
$previous_name = session_name("WebsiteID"); echo "新的session名為: $previous_name "; ?>
如何刪除session?
1、unset ($_SESSION['xxx']) 刪除單個(gè)session,unset($_SESSION['xxx']) 用來(lái)unregister一個(gè)已注冊(cè)的session變量。其作用和session_unregister()相同。 session_unregister()在PHP5中不再使用,可將之打入冷宮。
unset($_SESSION) 此函數(shù)千萬(wàn)不可使用,它會(huì)將全局變量$_SESSION銷毀,而且還沒(méi)有可行的辦法將其恢復(fù)。用戶也不再可以注冊(cè)$_SESSION變量。
2、$_SESSION=array() 刪除多個(gè)session
3、 session_destroy()結(jié)束當(dāng)前的會(huì)話,并清空會(huì)話中的所有資源。。該函數(shù)不會(huì)unset(釋放)和當(dāng)前session相關(guān)的全局變量 (globalvariables),也不會(huì)刪除客戶端的session cookie.PHP默認(rèn)的session是基于cookie的,如果要?jiǎng)h除cookie的話,必須借助setcookie()函數(shù)。
返回值:布爾值。
功能說(shuō)明:這個(gè)函數(shù)結(jié)束當(dāng)前的session,此函數(shù)沒(méi)有參數(shù),且返回值均為true
session_unset() 如果使用了$_SESSION,則該函數(shù)不再起作用。由于PHP5必定要使用$_SESSION,所以此函數(shù)可以打入冷宮了。
下面是PHP官方關(guān)于刪除session的案例:
<?php // 初始化session. session_start(); /*** 刪除所有的session變量..也可用unset($_SESSION[xxx])逐個(gè)刪除。****/ $_SESSION = array(); /***刪除sessin id.由于session默認(rèn)是基于cookie的,所以使用setcookie刪除包含session id的cookie.***/ if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); } // 最后徹底銷毀session. session_destroy(); ?>
由此我們可以得出刪除Session的步驟:
- session_start()
- $_SESSION=array()/unset($_SESSION['xxx'])
- session_destroy()
解決PHP Session不過(guò)期以及SessionId保持不變的問(wèn)題
session 回收機(jī)制:
PHP采用Garbage Collection process對(duì)過(guò)期session進(jìn)行回收,然而并不是每次session建立時(shí),都能夠喚起 ‘garbage collection' process ,gc是按照一定概率啟動(dòng)的。這主要是出于對(duì)服務(wù)器性能方面的考慮,每個(gè)session都觸發(fā)gc,瀏覽量大的話,服務(wù)器吃不消,然而按照一定概率開(kāi)啟gc,當(dāng)流覽量大的時(shí)候,session過(guò)期機(jī)制能夠正常運(yùn)行,而且服務(wù)器效率得到節(jié)省。細(xì)節(jié)應(yīng)該都是多年的經(jīng)驗(yàn)積累得出的。
三個(gè)與PHP session過(guò)期相關(guān)的參數(shù)(php.ini中):
- session.gc_probability = 1
- session.gc_divisor = 1000
- session.gc_maxlifetime = 1440
gc啟動(dòng)概率 = gc_probability / gc_divisor = 0.1%
session過(guò)期時(shí)間 gc_maxlifetime 單位:秒
當(dāng)web服務(wù)正式提供時(shí),session過(guò)期概率就需要根據(jù)web服務(wù)的瀏覽量和服務(wù)器的性能來(lái)綜合考慮session過(guò)期概率。為每個(gè)session都開(kāi)啟gc,顯然是不明智的,感覺(jué)有點(diǎn)“碰運(yùn)氣”的感覺(jué),要是訪問(wèn)量小命中幾率就小。我在本機(jī)測(cè)試過(guò)程中,幾乎都沒(méi)有被命中過(guò),sessionid幾天都不變,哪怕機(jī)器重啟。測(cè)試過(guò)程中,這個(gè)過(guò)期概率值要設(shè)置大一點(diǎn)命中幾率才高點(diǎn)。
通過(guò)修改php配置文件的過(guò)期概率值,可以“碰運(yùn)氣”式的設(shè)置session過(guò)期,那有沒(méi)有更好的辦法呢?
下面寫的這個(gè)session類可以徹底解決session不過(guò)期以及sessionid不變的問(wèn)題。
<?php /** * 擴(kuò)展Session類(簡(jiǎn)單封裝) * * @author slimboy * */ class Session { /** * 初始化 */ static function _init(){ ini_set('session.auto_start', 0); //Session::start(); } /** * 啟動(dòng)Session */ static function start() { session_start(); } /** * 設(shè)置Session * * @param $name Session名稱 * @param $value 值 * @param $time 超時(shí)時(shí)間(秒) */ public static function set($name,$value,$time){ if(empty($time)){ $time = 1800; //默認(rèn)值 } $_SESSION[$name] = $value; $_SESSION[$name.'_Expires'] = time() + $time; } /** * 獲取Session值 * * @param $name Session名稱 */ public static function get($name){ //檢查Session是否已過(guò)期 if(isset($_SESSION[$name.'_Expires']) && $_SESSION[$name.'_E xpires']>time()){ return $_SESSION[$name]; }else{ Session::clear($name); return null; } } /** * 設(shè)置Session Domain * * @param $sessionDomain 域 * @return string */ static function setDomain($sessionDomain = null) { $return = ini_get('session.cookie_domain'); if(!empty($sessionDomain)) { ini_set('session.cookie_domain', $sessionDomain);//跨 域訪問(wèn)Session } return $return; } /** * 清除某一Session值 * * @param $name Session名稱 */ static function clear($name){ unset($_SESSION[$name]); unset($_SESSION[$name.'_Expires']); } /** * 重置銷毀Session */ static function destroy(){ unset($_SESSION); session_destroy(); } /** * 獲取或設(shè)置Session id */ static function sessionid($id=null){ return session_id($id); } } ?> 簡(jiǎn)單調(diào)用: <?php //設(shè)置session Session::set('UserId', $userid, 3600); //讀取session $userId = Session::get('UserId'); ?>
- 詳解php設(shè)置session(過(guò)期、失效、有效期)
- PHP中設(shè)置一個(gè)嚴(yán)格30分鐘過(guò)期Session面試題的4種答案
- php中實(shí)現(xiàn)精確設(shè)置session過(guò)期時(shí)間的方法
- php中session過(guò)期時(shí)間設(shè)置及session回收機(jī)制介紹
- PHP中怎樣保持SESSION不過(guò)期 原理及方案介紹
- 解析PHP的session過(guò)期設(shè)置
- PHP中的session永不過(guò)期的解決思路及實(shí)現(xiàn)方法分享
- php 如何設(shè)置一個(gè)嚴(yán)格控制過(guò)期時(shí)間的session
相關(guān)文章
字符串長(zhǎng)度函數(shù)strlen和mb_strlen的區(qū)別示例介紹
strlen和mb_strlen的區(qū)別,但是對(duì)于一些初學(xué)者來(lái)說(shuō),如果不看手冊(cè),也許不太清楚其中的區(qū)別,下面與大家分享下兩者之間的區(qū)別2014-09-09PHP 之 寫時(shí)復(fù)制介紹(Copy On Write)
很多時(shí)候,我們會(huì)因?yàn)橐恍┬g(shù)語(yǔ)而對(duì)其概念產(chǎn)生莫測(cè)高深的恐懼,而其實(shí),他們的基本原理往往非常簡(jiǎn)單。本小節(jié)將介紹PHP中寫時(shí)復(fù)制這種策略的實(shí)現(xiàn)2014-05-05屏蔽機(jī)器人從你的網(wǎng)站搜取email地址的php代碼
屏蔽機(jī)器人從你的網(wǎng)站搜取email地址然后發(fā)垃圾郵件的處理方法,需要的朋友可以參考下2012-11-11PHP實(shí)現(xiàn)十進(jìn)制、二進(jìn)制、八進(jìn)制和十六進(jìn)制轉(zhuǎn)換相關(guān)函數(shù)用法分析
這篇文章主要介紹了PHP實(shí)現(xiàn)十進(jìn)制、二進(jìn)制、八進(jìn)制和十六進(jìn)制轉(zhuǎn)換相關(guān)函數(shù)用法,結(jié)合具體實(shí)例形式較為詳細(xì)的分析了php各種常見(jiàn)的進(jìn)制轉(zhuǎn)換函數(shù)功能、參數(shù)、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-04-04php轉(zhuǎn)換上傳word文件為PDF的方法【基于COM組件】
這篇文章主要介紹了php轉(zhuǎn)換上傳word文件為PDF的方法,結(jié)合實(shí)例形式分析了php基于COM組件針對(duì)word文件的格式轉(zhuǎn)換相關(guān)操作技巧,需要的朋友可以參考下2019-06-06php+ajax實(shí)現(xiàn)無(wú)刷新數(shù)據(jù)分頁(yè)的辦法
這篇文章主要介紹了php+ajax實(shí)現(xiàn)無(wú)刷新分頁(yè)的方法,詳細(xì)講述了數(shù)據(jù)庫(kù)的創(chuàng)建、Ajax文件的實(shí)現(xiàn)及PHP調(diào)用方法,需要的朋友可以參考下2015-11-11