首先說明一點:session不一定必須依賴cookie,只是php默認客戶端sessionid基於cookie方式保存。
到此,我想你也應該了解了php默認的session客戶端保存方式是基於cookie的,所以一旦客戶端禁用Cookie,那么session跨頁將會失效,不知道這么描述是否合適,通俗的說無狀態的東西要變的有狀態,只能兩邊都進行比對,如果用cookie方式保存的SessionID,客戶端這邊的比對條件就放到cookie里,所以客戶端禁用cookie,session便也會隨之失效。php的session客戶端ID一般有兩種保存方式:cookie和url方式。如果是cookie中保存session ID,就可以看到瀏覽器的cookie中有一個PHPSESID變量(可以通過firefox查看)。如果是URL傳遞的(建議使用隱藏表單傳遞),就可以看到形如:index.php?PHPSESID=ves0d7uvdsab9k6sig73mnn592的URL。
demo1.php
<?php
session_start();
$_SESSION['blog']='http://blog.jb51.net';
echo "<a href='demo2.php'>test2</a>";
?>
demo2.php
<?php
session_start();
echo 'session值為'.$_SESSION['blog'];
?>
運行上面的代碼,在客戶端cookie正常情況下,我么可以在demo2.php中打印出$_SESSION['blog']的值為:http://blog.jb51.net。但是,現在如果你手動禁用客戶端的cookie,再運行該實例,可能就得不到結果了。因為默認的客戶端sessionid保存方式在跨頁后,讀取不到前一頁的sessionid,當執行session_start();將又會產生一個session文件,與之對應產生相應的session id,用這個session id是取不出前面提到的第一個session文件中的變量的,因為這個session id不是打開它的“鑰匙”。如果在session_start();之前加代碼session_id($sessionid);將不產生新的session文件,直接讀取與這個id對應的session文件。簡單的說就是在前一頁取得session id,然后想辦法傳遞到下一頁,在下一頁的session_start();代碼之前加代碼session_id(傳過來的sessionid);
demo.php
<?php
$sid = $_GET['sid'];
if(!empty($sid)){
session_id($sid);
session_start();
}else{
session_start();
$sid = session_id();
}
?>
<form action="demo2.php?sid=<?php echo $sid ?>" method="post">
<input type="text" name="id" value="100" />
<input type="submit" value="提交"/>
</form>
demo2.php
<?php
$sid = $_GET['sid'];
if(!empty($sid)){
session_id($sid);
session_start();
}else{
session_start();
$sid = session_id();
}
$id = $_POST['id'];
$key = 'poll_'.$id;
if($id!=''){
echo $key = 'poll'.$id;
if(!empty($_SESSION[$key])){
$_SESSION[$key]=$_SESSION[$key] + 1;
}else{
$_SESSION[$key]=1;
setcookie($key ,$id+1,time()+3600*24);
}
echo '<script>alert("success");javascript:location.href="demo.php?sid='.$sid.'";</script>';
}else{
echo '<script>alert("failed!ID Null");javascript:history.back(-1);</script>';
}
?>
除此之外,我們還可以將客戶端PHPSESID存放到文件中,如:
demo.php
session_start();
$_SESSION['blogdomain']= 'http://blog.jb51.net';
$sid=session_id();
$fp=fopen("D:\tmp\websid.txt","w+");
fwrite($fp,$sid);
fclose($fp);
echo '<a href="demo2.php">demo2</a>';
demo2.php
$fp=fopen("D:\tmp\websid.txt","r");
$sid=fread($fp,1024);
fclose($fp);
session_id($sid);
session_start();
print_r($_SESSION);
當客戶端禁用cookie,可以通過以下幾種方式改變session對客戶端cookie的依賴,使session拋開客戶端cookie:
設置php.ini中的session.use_trans_sid = 1或者編譯時打開了--enable-trans-sid選項,讓PHP自動跨頁傳遞session id。當session.use_trans_sid為有效時,session.use_only_cookies一定要設置為無效0。
手動通過URL傳值、隱藏表單傳遞session id。
用文件、數據庫等形式保存session_id,在跨頁過程中手動調用。
改變session客戶端ID保存方式:
session.use_cookies //控制客戶端保存SessionID時使用哪一種方式,當它為“1”時,就說明啟動了session cookie(初始值為1)
可以使用上面我們提到的函數來查詢得到目前的session id:echo $_COOKIE["PHPSESSID"];
但是,如果client的瀏覽器不支持cookie的話,即使session.use_cookies這個參數的值等於“1”,用上述的查詢也只會得到null。
php.ini中兩個和該選項相關的配置參數:
session.use_cookies = 1 //是否使用cookies(默認值為1)
session.use_only_cookies=1 //為1時只使用cookie;為0時可使用cookie和其它方式,這時如果客戶端cookie可用,則session還是默認用cookie(默認值為1)
注意:如果客戶的瀏覽器是支持cookie的,強烈推薦“session.use_only_cookies = 1”,當session.use_only_cookies為有效時,即使想通過URL來傳遞session id也會被認為無效,這樣可以減少通過sessionid被攻擊的可能性。
在php代碼頁面中設置方式:
ini_set('session.use_cookies','1');
ini_set('session.use_only_cookies','1');
