程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP session與cookie

PHP session與cookie

編輯:關於PHP編程

PHP SESSION原理

session是在服務器端保持用戶會話數據的一種方法,對應的cookie是在客戶端保持用戶數據。HTTP協議是一種無狀態協議,服務器響應完後就失去了與浏覽器的聯系,cookie引入浏覽器,使得數據跨越頁面交換。

首先客戶端和服務器端建立一一聯系,每個客戶端都有一個唯一標識,這樣服務器才能識別出來。建議唯一標識的方法有兩種:cookie或者通過GET方式指定。默認配置的PHP使用session的時會建立一個名叫”PHPSESSID”的cookie(可以通過php.ini修改session.name值指定),如果客戶端禁用cookie,你也可以指定通過GET方式把session id傳到服務器(修改php.ini中session.use_trans_sid等參數)。

客戶端將session id傳遞到服務器,服務器根據session id找到對應的文件,讀取的時候對文件內容進行反序列化就得到session的值,保存的時候先序列化再寫入。

事實就是這樣,如果服務器不支持session或者你想自定義session,完全可以DIY,通過PHP的uniqid生成永不重復的session id,然後找個地方存儲session的內容即可,還可以把session存儲在MySQL數據庫中。

所謂的session其實就是客戶端一個session id,服務器端一個session file,新建session時,告訴服務器要生成一個cookie以及准備好session文件,要不然你的session內容怎麼存;讀取session時告訴服務器,趕緊根據session id把session文件反序列化。

session影響系統性能

session在大訪問量網站上確實影響系統性能,影響性能的原因之一由文件系統設計造成,在同一個目錄下超過10000個文件時,文件的定位將非常耗時,PHP支持session目錄hash,我們可以通過修改php.ini中session.save_path =“2;/path/to/session/dir”,那麼session將存儲在兩級子目錄中,每個目錄有16個子目錄[0~f],不過好像PHPsession不支持創建目錄,你需要事先把那麼些目錄創建好 。

還有一個問題就是小文件的效率問題,一般我們的session數據都不會太大(1~2K),如果有大量這樣1~2K的文件在磁盤上,IO效率肯定會很差。可以通過緩存memcache和mysql數據庫提供效率。

session的同步

前端可能有很多台服務器,用戶在A服務器上登錄了,種下了session信息,然後訪問網站的某些頁面沒准跳到B服務器上去了,如果這個時候B服務器上沒有session信息又沒有做特殊處理,可能就會出問題了。

session同步有很多種,如果你是存儲在memcached或者MySQL中,那就很容易了,指定到同樣的位置即可,如果是文件形式的,你可以用NFS統一存儲。

(NFS是Network File System的簡寫,即網絡文件系統.網絡文件系統是FreeBSD支持的文件系統中的一種,也被稱為NFS. NFS允許一個系統在網絡上與他人共享目錄和文件。通過使用NFS,用戶和程序可以像訪問本地文件一樣訪問遠端系統上的文件。)

還有一種方式是通過加密的cookie來實現,用戶在A服務器上登錄成功,在用戶的浏覽器上種上一個加密的cookie,當用戶訪問B服務器時,檢查有無session,如果有當然沒問題,如果沒有,就去檢驗cookie是否有效,cookie有效的話就在B服務器上重建session。這種方法其實很有用,如果網站有很多個子頻道,服務器也不在一個機房,session沒辦法同步又想做統一登錄那就太有用了。

當然還有一種方法就是在負載均衡那一層保持會話,把訪問者綁定在某個服務器上,他的所有訪問都在那個服務器上就不需要session同步了。


<?php

session_start();

if(isset($_SESSION['test_sess'])){

     $_SESSION['test_sess']++;

}else{

     $_SESSION['test_sess'] = 0;

}

echo$_SESSION['test_sess'];

?>;

第一次請求服務器:

GET/test.php HTTP/1.1

Accept:*/*

Referer:http://localhost/

Accept-Language:zh-cn

Accept-Encoding:gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)

Host:localhost

Connection:Keep-Alive

服務器第一次返回:

HTTP/1.1200 OK

Date:Fri, 26 Aug 2005 07:44:22 GMT

Server:Apache/2.0.54 (Win32) SVN/1.2.1 PHP/5.0.4 DAV/2

X-Powered-By:PHP/5.0.4

Set-Cookie:PHPSESSID=bmmc3mfc94ncdr15ujitjogma3; path=/

Expires:Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control: no-store, no-cache,must-revalidate, post-check=0, pre-check=0

Pragma:no-cache

Content-Length:1

Keep-Alive:timeout=15, max=99

Connection:Keep-Alive

Content-Type:text/html; charset=utf-8

Content-Language:Off

第二次請求服務器:

GET/test.php HTTP/1.1

Accept:*/*

Referer:http://localhost/

Accept-Language:zh-cn

Accept-Encoding:gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)

Host:localhost

Connection:Keep-Alive

Cookie: PHPSESSID=bmmc3mfc94ncdr15ujitjogma3

服務器第二次返回:

HTTP/1.1200 OK

Date:Fri, 26 Aug 2005 07:44:23 GMT

Server:Apache/2.0.54 (Win32) SVN/1.2.1 PHP/5.0.4 DAV/2

X-Powered-By:PHP/5.0.4

Set-Cookie:PHPSESSID=bmmc3mfc94ncdr15ujitjogma3; path=/

Expires:Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control: no-store, no-cache,must-revalidate, post-check=0, pre-check=0

Pragma:no-cache

Content-Length:1

Keep-Alive:timeout=15, max=98

Connection:Keep-Alive

Content-Type:text/html; charset=utf-8

Content-Language:Off

仔細對比這些輸出,第二次請求比第一次請求多出來的就是:

Cookie:PHPSESSID=bmmc3mfc94ncdr15ujitjogma3

這個header將會向服務器發送一個cookie信息,告訴服務器我有一個cookie,名字叫PHPSESSID,內容是bmmc3mfc94ncdr15ujitjogma3。

這個cookie是怎麼來的呢?看第一次服務器返回的信息裡邊有:

Set-Cookie:PHPSESSID=bmmc3mfc94ncdr15ujitjogma3; path=/

這是服務器向客戶端浏覽器寫一個cookie,名字是PHPSESSID,值是bmmc3mfc94ncdr15ujitjogma3,這個值實際就是所謂的session_id。

繼續看第二次向服務器發出的請求,仍然向服務器發送了PHPSESSID這個cookie

可以得到以下結論:

1、只要使用了session,就會通過cookie的方式向客戶端浏覽器發送session

2、每次向服務器發出請求的時候,本地浏覽器會把cookie附帶在請求信息中

COOKIE

    cookie 是一種在遠程浏覽器端儲存數據並以此來跟蹤和識別用戶的機制。

PHP在http 協議的頭信息裡發送cookie,因此setcookie()函數必須在其它信息被輸出到浏覽器前調用。

原理.

a.服務器通過隨著響應發送一個http 的Set-Cookie 頭,在客戶機中設置一個cookie(多個cookie 要多個頭)。

   b.客戶端自動向服務器端發送一個http 的cookie 頭,服務器接收讀取。

     HTTP/1.x 200 OK

     X-Powered-By: PHP/5.2.1

  Set-Cookie:TestCookie=something from somewhere; path=/

     Expires: Thu, 19 Nov 2007 18:52:00 GMT

     Cache-Control: no-store, no-cache,must-revalidate,      post-check=0,pre-check=0

   Pragma: no-cache

   Content-type: text/html

 這一行實現了cookie 功能,收到這行後

 Set-Cookie: TestCookie=something fromsomewhere; path=/

浏覽器將在客戶端的磁盤上創建一個cookie 文件。

下面的同樣的效果:

setcookie('TestCookie','something   from somewhere','/');

header('Set-Cookie:TestCookie=something from somewhere; path=/')

常見問題解決:

1) 用 setcookie()時有錯誤提示,可能是因為調用setcookie()前面有輸出或空格。

2) $_COOKIE 受magic_quotes_gpc 影響,可能自動轉義。

3) 使用的時候,有必要測試用戶是否支持cookie。

下面以用戶登錄為例分析session和cookie

HTTP協議是一種無狀態協議,服務器響應完用戶的請求,就失去了與浏覽器的聯系,PHP是如何實現session的。

用戶第一次訪問服務器時,因為沒有session信息,需要登錄驗證,用戶通過表單把用戶名,密碼,驗證碼等信息提交給服務器,服務器在驗證用戶的合法性之前先對數據進行預處理。通過到數據庫驗證,用戶是合法的,這個時候服務器會給浏覽器信息中包含Set-Cookie: PHPSESSID=bmmc3mfc94ncdr15ujitjogma3;這樣的信息,這樣浏覽器會把信息寫到本地文件中,其中PHPSESSID為唯一標識符。同時服務器也會在指定的文件把序列化的session信息保存在文件中。當用戶再次請求時,浏覽器會把對應cookie中的PHPSESSID也發送給服務器,服務器得到PHPSESSID,會到session文件中驗證,如果驗證成功,就直接登錄。從而類似的可以實現數據在不同用戶頁面之前的傳遞。session中的值是key-value。

session影響系統性能

session在大訪問量網站上確實影響系統性能,影響性能的原因之一由文件系統設計造成,在同一個目錄下超過10000個文件時,文件的定位將非常耗時,PHP支持session目錄hash,我們可以通過修改php.ini中session.save_path =“2;/path/to/session/dir”,那麼session將存儲在兩級子目錄中,每個目錄有16個子目錄[0~f],不過好像PHPsession不支持創建目錄,你需要事先把那麼些目錄創建好 。

還有一個問題就是小文件的效率問題,一般我們的session數據都不會太大(1~2K),如果有大量這樣1~2K的文件在磁盤上,IO效率肯定會很差。可以通過緩存memcache和mysql數據庫提供效率。

session的同步

前端可能有很多台服務器,用戶在A服務器上登錄了,種下了session信息,然後訪問網站的某些頁面沒准跳到B服務器上去了,如果這個時候B服務器上沒有session信息又沒有做特殊處理,可能就會出問題了。

session同步有很多種,如果你是存儲在memcached或者MySQL中,那就很容易了,指定到同樣的位置即可,如果是文件形式的,你可以用NFS統一存儲。

(NFS是Network File System的簡寫,即網絡文件系統.網絡文件系統是FreeBSD支持的文件系統中的一種,也被稱為NFS. NFS允許一個系統在網絡上與他人共享目錄和文件。通過使用NFS,用戶和程序可以像訪問本地文件一樣訪問遠端系統上的文件。)

還有一種方式是通過加密的cookie來實現,用戶在A服務器上登錄成功,在用戶的浏覽器上種上一個加密的cookie,當用戶訪問B服務器時,檢查有無session,如果有當然沒問題,如果沒有,就去檢驗cookie是否有效,cookie有效的話就在B服務器上重建session。這種方法其實很有用,如果網站有很多個子頻道,服務器也不在一個機房,session沒辦法同步又想做統一登錄那就太有用了。

還有一種方法就是在負載均衡那一層保持會話,把訪問者綁定在某個服務器上,其他所有訪問都在那個服務器上就不需要

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved