PHP 中cookie 和 session 的分析

HP  中cookie 和session 的分析 php

                                     -- 與客戶端進行交互
1. PHP 的COOKIE html

    cookie 是一種在遠程瀏覽器端儲存數據並以此來跟蹤和識別用戶的機制。
    PHP 在http 協議的頭信息裏發送cookie,所以  setcookie()     函數必須在其它信息被輸出到瀏覽器
前調用,這和對  header()    函數的限制相似。 web

1.1 設置cookie: 數據庫

   能夠用 setcookie()或 setrawcookie()函數來設置 cookie。也能夠經過向客戶端直接發送http  頭來
設置。
    1.1.1  使用 setcookie()函數設置cookie:
bool setcookie ( string name [, string value [, int expire [, string path [, string domain [, bool secure [, bool
httponly]]]]]] )
   name: cookie 變量名
   value: cookie 變量的值
   expire: 有效期結束的時間
   path: 有效目錄
   domain: 有效域名,頂級域惟一
   secure: 若是值爲 1,則cookie 只能在https 鏈接上有效,若是爲默認值 0,則http 和 https 均可
以。
例子: 編程

代碼片斷
   <?php
    $value = 'something from somewhere'; 數組

    setcookie("TestCookie", $value); /* 簡單 cookie設置 */
    setcookie("TestCookie", $value, time()+3600); /* 有效期 1個小時 */
    setcookie("TestCookie", $value, time()+3600, "/~rasmus/", 瀏覽器

    ".example.com", 1); /* 有效目錄 /~rasmus,有效域名 example.com及其全部子域名
    */
    ?> 緩存

    設置多個 cookie  變量:setcookie('var[a]','value');  用數組來表示變量,但他的下標不用引號。這
樣就能夠用$_COOKIE[‘var’][‘a’]來讀取該COOKIE 變量。 安全

    1.1.2.  使用 header()設置cookie;
    header("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[;...]]");
    後面的參數和上面列出 setcookie 函數的參數同樣。
    好比: 服務器

代碼片斷 

    $value = 'something from somewhere';
   header("Set-Cookie:name=$value");

1.2 Cookie 的讀取:

    直接用php  內置超級全局變量$_COOKIE 就能夠讀取瀏覽器端的cookie。
    上面例子中設置了cookie "TestCookie",如今咱們來讀取:

       代碼片斷
   print $_COOKIE['TestCookie'];

    COOKIE 是否是被輸出了?!

1.3  刪除cookie

    只需把有效時間設爲小於當前時間,和把值設置爲空。例如:

    代碼片斷

    setcookie("name", "", time()-1);

    用header()相似。

1.4  常見問題解決:

    1) 用 setcookie()時有錯誤提示,多是由於調用setcookie()前面有輸出或空格。也可能你的文
       檔是從其餘字符集轉換過來,文檔後面可能帶有 BOM 簽名(就是在文件內容添加一些隱藏
       的BOM 字符)。解決的辦法就是使你的文檔不出現這種狀況。還有經過使用ob_start()函數
       也能處理一點。
    2) $_COOKIE 受magic_quotes_gpc 影響,可能自動轉義。
    3) 使用的時候,有必要測試用戶是否支持cookie。

1.5 cookie 工做機理:

    有些學習者比較衝動,沒心思把原理研究,因此我把它放後面。
    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 from somewhere; path=/

    瀏覽器將在客戶端的磁盤上建立一個cookie 文件,並在裏面寫入:

    TestCookie=something from somewhere;
    /

    這一行就是咱們用 setcookie('TestCookie','something   from  somewhere','/'); 的結果。也就是用
header('Set-Cookie: TestCookie=something from somewhere; path=/');的結果。

2. PHP 的SESSION

    session 使用過時時間設爲0 的cookie,而且將一個稱爲session ID 的惟一標識符(一長串字符串),
在服務器端同步生成一些 session 文件(能夠本身定義 session 的保存類型),與用戶機關聯起來。web
應用程序存貯與這些 session 相關的數據,而且讓數據隨着用戶在頁面之間傳遞。
    訪問網站的來客會被分配一個惟一的標識符,即所謂的 SESSION                       ID。它要麼存放在客戶端的
cookie,要麼經由  URL  傳遞。
    SESSION 容許用戶註冊任意數目的變量並保留給各個請求使用。當來客訪問網站時,PHP  會自
動(若是   session.auto_start 被設爲   1 )或在用戶請求時(由   session_start()        明確調用或
session_register() 暗中調用)檢查請求中是否發送了特定的SESSION ID。若是是,則以前保存的環
境就被重建。

2.1 SESSION ID 的傳送

    2.1.1 經過 cookie 傳送 SESSION ID
    使用 session_start()調用 session,服務器端在生成session 文件的同時,生成 session ID 哈希值(將任意長度的二進制值映射爲固定長度的較小二進制值,這個小的二進制值稱爲哈希值。哈希值是一段數據惟一且極其緊湊的數值表示形式。若是散列一段明文並且哪怕只更改該段落的一個字母,隨後的哈希都將產生不一樣的值。要找到散列爲同一個值的兩個不一樣的輸入,在計算上是不可能的。)和
默認值爲PHPSESSID 的session name,並向客戶端發送變量爲(默認的是)PHPSESSID(session name),
值爲一個 128 位的哈希值。服務器端將經過該 cookie 與客戶端進行交互。
    session 變量的值經php  內部序列化後保存在服務器機器上的文本文件中,和客戶端的變量名默
認狀況下爲PHPSESSID 的coolie 進行對應交互。
    即服務器自動發送了 http           頭:header('Set-Cookie:  session_name()=session_id();  path=/'); 即
setcookie(session_name(),session_id());
    當從該頁跳轉到的新頁面並調用session_start()後,PHP 將檢查與給定ID 相關聯的服務器端存貯
的session 數據,若是沒找到,則新建一個數據集。
    2.1.2 經過 URL 傳送 session ID
    只有在用戶禁止使用cookie 的時候才用這種方法,由於瀏覽器cookie 已經通用,爲安全起見,
可不用該方法。
    <a href="p.php?<?php print session_name() ?>=<?php print session_id() ?>">xxx</a>,也能夠經過
POST 來傳遞 session 值。

2.2 session 基本用法實例

代碼片斷
    <?php
    // page1.php
    session_start();
    echo 'Welcome to page #1';

    /* 建立 session變量並給 session變量賦值 */

    $_SESSION['favcolor'] = 'green';
    $_SESSION['animal'] = 'cat';
    $_SESSION['time'] = time();

    // 若是客戶端使用 cookie,可直接傳遞 session到page2.php
   echo '<br /><a href="page2.php">page 2</a>';

    // 若是客戶端禁用 cookie
   echo '<br /><a href="page2.php?' . SID . '">page 2</a>';
    /*

    默認php5.2.1下,SID只有在 cookie被寫入的同時纔會有值,若是該 session
    對應的 cookie 已經存在,那麼 SID將爲 (未定義)空
    */
    ?>

代碼片斷
   <?php
    // page2.php
    session_start();

   print $_SESSION['animal']; // 打印出單個 session
   var_dump($_SESSION); // 打印出page1.php傳過來的 session值
    ?>

2.3  使用session 函數控制頁面緩存

    不少狀況下,咱們要肯定咱們的網頁是否在客戶端緩存,或要設置緩存的有效時間,好比咱們
的網頁上有些敏感內容而且要登陸才能查看,若是緩存到本地了,能夠直接打開本地的緩存就能夠
不登陸而瀏覽到網頁了。
    使用 session_cache_limiter('private');能夠控制頁面客戶端緩存,必須在 session_start()以前調用。
    更多參數見http://blog.chinaunix.net/u/27731/showart.php?id=258087  的客戶端緩存控制。
    控制客戶端緩存時間用 session_cache_expire(int);  單位(s)。也要在session_start()前調用。
    這只是使用 session 的狀況下控制緩存的方法,咱們還能夠在header()中控制控制頁面的緩存。

2.4  刪除session

    要三步實現。

    代碼片斷
   <?php

    session_destroy();      // 第一步: 刪除服務器端 session文件,這使用
    setcookie(session_name(),'',time()-3600);      //  第 二 步 : 刪 除 實 際 的
    session:

    $_SESSION = array();     // 第三步: 刪除$_SESSION全局變量數組
    ?>

2.5 session 在PHP 大型web 應用中的使用

    對於訪問量大的站點,用默認的 session  存貯方式並不適合,目前最優的方法是用數據庫存取
session。這時,函數bool session_set_save_handler ( callback open, callback close, callback read, callback
write, callback destroy, callback gc )就是提供給咱們解決這個問題的方案。
    該函數使用的6 個函數以下:
    1.  bool open() 用來打開會話存儲機制。
    2.  bool close() 關閉會話存儲操做。
    3.  mixde read() 從存儲中裝載session 數據時使用這個函數。
    4.  bool write() 將給定 session ID 的全部數據寫到存儲中。
    5.  bool destroy() 破壞與指定的 session ID 相關聯的數據。
    6.  bool gc() 對存儲系統中的數據進行垃圾收集。
    例子見php 手冊 session_set_save_handler() 函數。
    若是用類來處理,用

    代碼片斷
    session_set_save_handler(

      array('className','open'),
      array('className','close'),
      array('className','read'),
      array('className','write'),
      array('className','destroy'),
      array('className','gc'),
    )

    調用className 類中的 6 個靜態方法。className 能夠實例化對象就不用調用靜態方法,可是用
    靜態成員不用生成對象,性能更好。

2.6  經常使用session 函數:

    bool session_start(void) 初始化 session。
    bool session_destroy(void) 刪除服務器端 session 關聯文件。
    string session_id() 當前session 的id。
    string session_name() 當前存取的session 名稱,也就是客戶端保存session ID 的cookie 名稱.默
認PHPSESSID。
    array session_get_cookie_params() 與這個session 相關聯的 session 的細節。
    string session_cache_limiter() 控制使用 session 的頁面的客戶端緩存。
    ini session_cache_expire() 控制客戶端緩存時間。
    bool session_destroy() 刪除服務器端保存 session 信息的文件。
    void session_set_cookie_params   (   int   lifetime   [,   string   path   [,   string   domain   [,   bool   secure   [,   bool
httponly]]]] ) 設置與這個session 相關聯的 session 的細節。
    bool session_set_save_handler ( callback open, callback close, callback read, callback write, callback
destroy, callback gc ) 定義處理session 的函數(不是使用默認的方式)。
    bool session_regenerate_id([bool delete_old_session]) 分配新的session id

2.7 session 安全問題

    攻擊者經過投入很大的精力嘗試得到現有用戶的有效 session ID,有了session id,他們就有可能
可以在系統中擁有與此用戶相同的能力。
    所以,咱們主要解決的思路是效驗session ID 的有效性。

代碼片斷
   <?php

      if(!isset($_SESSION['user_agent'])){

           $_SESSION['user_agent'] = $_SERVER['REMOTE_ADDR'] .

      $_SERVER['HTTP_USER_AGENT'];

      }

      /* 若是用戶 session ID是僞造 */

      elseif ($_SESSION['user_agent'] != $_SERVER['REMOTE_ADDR'] .

      $_SERVER['HTTP_USER_AGENT']) {

          session_regenerate_id();

      }

    ?>

2.8 Session 經過cookie 傳遞和經過SID 傳遞的不一樣

    在 php5.2.1  的session  的默認配置的狀況下,當生成session  的同時,服務器端將在發送header
set-cookie 同時生成預約義超級全局變量 SID(也就是說,寫入 cookie              和拋出 SID   是等價的),當
$_COOKIE['PHPSESSID']存在之後,將再也不寫入 cookie,也再也不生成超級全局變量SID,此時,SID
將是空的。

2.9 session 使用實例

代碼片斷
   <?php
    /**

    * 效驗 session的合法性
    *
    */
    function sessionVerify() {
       if(!isset($_SESSION['user_agent'])){
           $_SESSION['user_agent'] = MD5($_SERVER['REMOTE_ADDR']
           .$_SERVER['HTTP_USER_AGENT']);
       }

       /* 若是用戶 session ID是僞造,則從新分配 session ID */
       elseif ($_SESSION['user_agent']!=MD5($_SERVER['REMOTE_ADDR']
       . $_SERVER['HTTP_USER_AGENT'])) {
            session_regenerate_id();
       }
    }

 /**

    * 銷燬 session
    * 三步完美實現,不可漏
    *
    */
    function sessionDestroy() {
        session_destroy();
        setcookie(session_name(),'',time()-3600);
        $_SESSION = array();
    }
    ?>

註明:   session 出現頭信息已經發出的緣由與cookie 同樣。   在php5  中,全部php     session  的註冊表配置選項都是編程時可配置的,通常狀況下,咱們是不用 修改其配置的。要了解php 的session 註冊表配置選項,請參考手冊的 Session 會話處理函數處。

相關文章
相關標籤/搜索