http://www.jb51.net/article/52309.htm
大多數據情況下我們對於session過期時間使用的是默認設置的時間,而對於一些有特殊要求的情況下我們可以設置一下session過期時間。
對此,可以在PHP中,設置php.ini,找到session.gc_maxlifetime = 1440 #(PHP5默認24分鍾)
這里你可以隨便設置一下過期時間.但是有人說設置以后,好象不起作用!
其實不是不起作用,而是因為系統默認:
1
2
|
session.gc_probability = 1
session.gc_divisor = 1000
|
garbage collection 有個概率的,1/1000就是session 1000次才有一次被回收。
只要你的訪問量大了,那就能達到回收的效果.
或者你也可以設置一下session.gc_divisor 的值,
比如:session.gc_divisor = 1,這樣就能明顯的看到SESSION過期的效果了.
我們最常用的是在php程序中設置,如下例程序所示:
1
2
3
4
|
<?php
if
(!isset(
$_SESSION
[
'last_access'
])||(time()-
$_SESSION
[
'last_access'
])>60)
$_SESSION
[
'last_access'
] = time();
?>
|
這樣就搞定了,如果要設置已過期的話也可以在程序中實現:
1
2
3
|
<?php
unset(
$_SESSION
[
'last_access'
]);
// 或 $_SESSION['last_access']='';
?>
|
session有過期的機制:
session.gc_maxlifetime 原來session 過期是一個小概率的事件,分別使用session.gc_probability和session.gc_divisor 來確定運行session 中gc 的概率 session.gc_probability和session.gc_divisor的默認值分別為 1和100。分別為分子和分母 所以session中gc的概率運行機會為1% 。如果修改這兩個值,則會降低php的效率。所以這種方法是不對的!!
因此,修改php.ini文件中的gc_maxlifetime變量就可以延長session的過期時間了:(例如,我們把過期時間修改為86400秒)
session.gc_maxlifetime = 86400
然后,重啟你的web服務(一般是apache)就可以了。
session“回收”何時發生:
默認情況下,每一次php請求,就會有1/100的概率發生回收,所以可能簡單的理解為“每100次php請求就有一次回收發生”。這個概率是通過以下參數控制的
#概率是gc_probability/gc_divisor
1
2
|
session.gc_probability = 1
session.gc_divisor = 100
|
注意1:假設這種情況gc_maxlifetime=120,如果某個session文件最后修改時間是120秒之前,那么在下一次回收(1/100的概率)發生前,這個session仍然是有效的。
注意2:如果你的session使用session.save_path中使用別的地方保存session,session回收機制有可能不會自動處理過期session文件。這時需要定時手動(或者crontab)的刪除過期的session:
1
|
cd
/path/to/sessions
;
find
-cmin +24 |
xargs
rm
|
PHP中的session永不過期
不修改程序是最好的方法了,因為如果修改程序,測試部一定非常郁悶,那么只能修改系統環境配置,其實很 簡單,打開php.ini設置文件,修改三行如下:
1、session.use_cookies
把這個的值設置為1,利用cookie來傳遞sessionid
2、session.cookie_lifetime
這個代表SessionID在客戶端Cookie儲存的時間,默認是0,代表瀏覽器一關閉SessionID就作廢……就是因為這個所以PHP的 session不能永久使用! 那么我們把它設置為一個我們認為很大的數字吧,999999999怎么樣,可以的!就這樣。
3、session.gc_maxlifetime
這個是Session數據在服務器端儲存的時間,如果超過這個時間,那么Session數據就自動刪除! 那么我們也把它設置為99999999。
就這樣一切ok了,當然你不相信的話就測試一下看看——設置一個session值過個10天半個月的回來看看,如果你的電腦沒有斷電或者宕機,你仍然可以看見這個sessionid。
當然也可能你沒有控制服務器的權限並不能像我一樣幸運的可以修改php.ini設置,一切依靠我們自己也是有辦法的,當然就必須利用到客戶端存儲 cookie了,把得到的sessionID存儲到客戶端的cookie里面,設置這個cookie的值,然后把這個值傳遞給session_id()這 個函數,具體做法如下:
1
2
3
4
5
6
7
8
9
|
<?php
session_start();
// 啟動Session
$_SESSION
[
'count'
];
// 注冊Session變量Count
isset(
$PHPSESSID
)?session_id(
$PHPSESSID
):
$PHPSESSID
= session_id();
// 如果設置了$PHPSESSID,就將SessionID賦值為$PHPSESSID,否則生成SessionID
$_SESSION
[
'count'
]++;
// 變量count加1
setcookie(
'PHPSESSID'
,
$PHPSESSID
, time()+3156000);
// 儲存SessionID到Cookie中
echo
$count
;
// 顯示Session變量count的值
?>
|
session失效不傳遞
我們先寫個php文件:<?=phpinfo()?>, 傳到服務器去看看服務器的參數配置。
轉到session部分,看到session.use_trans_sid參數被設為了零。
這個參數指定了是否啟用透明SID支持,即session是否隨着URL傳遞。我個人的理解是,一旦這個參數被設為0,那么每個URL都會啟一個session。這樣后面頁面就無法追蹤得到前面一個頁面的session,也就是我們所說的無法傳遞。兩個頁面在服務器端生成了兩個session文件,且無關聯。(此處精確原理有待確認)
所以一個辦法是在配置文件php.ini里把session.use_trans_sid的值改成1。
當然我們知道,不是誰都有權限去改php的配置的,那么還有什么間接的解決辦法呢?
下面就用兩個實例來說明:
文件1 test1.php
1
2
3
4
5
6
7
8
9
10
|
<?php
//表明是使用用戶ID為標識的session
session_id(SID);
//啟動session
session_start();
//將session的name賦值為Havi
$_SESSION
[
'name'
]=
"Havi"
;
//輸出session,並設置超鏈接到第二頁test2.php
echo
"<a href="
test2.php
" rel="
external nofollow
" >"
.
$_SESSION
[
'name'
].
"</a>"
;
?>
|
文件2: test2.php
1
2
3
4
5
6
7
8
|
<?php
表明是使用用戶ID為標識的session
session_id(SID);
//啟動session
session_start();
//輸出test1.php中傳遞的session。
echo
"This is "
.
$_SESSION
[
'name'
];
?>
|
所以,重點是在session_start();前加上session_id(SID);,這樣頁面轉換時,服務器使用的是用戶保存在服務器session文件夾里的session,解決了傳遞的問題。
不過有朋友會反映說,這樣一來,多個用戶的session寫在一個SID里了,那Session的價值就發揮不出來了。所以還有一招來解決此問題,不用加session_id(SID);前提是你對服務器的php.ini有配置的權限:
output_buffering改成ON,道理就不表了。
第二個可能的原因是對服務器保存session的文件夾沒有讀取的權限,還是回到phpinfo.php中,查看session保存的地址:
1
|
session.save_path:
var
/tmp
|
所以就是檢查下var/tmp文件夾是否可寫。
寫一個文件:test3.php來測試一下:
1
2
3
|
<?php
echo
var_dump(
is_writeable
(
ini_get
(
"session.save_path"
)));
?>
|
如果返回bool(false),證明文件夾寫權限被限制了,那就換個文件夾咯,在你編寫的網頁里加入:
1
2
3
4
5
6
7
|
//設置當前目錄下session子文件夾為session保存路徑。
$sessSavePath
= dirname(
__FILE__
).
'/session/'
;
//如果新路徑可讀可寫(可通過FTP上變更文件夾屬性為777實現),則讓該路徑生效。
if
(
is_writeable
(
$sessSavePath
) &&
is_readable
(
$sessSavePath
))
{
session_save_path(
$sessSavePath
);
}
|