首頁  >  文章  >  後端開發  >  PHP保持Session不過期的方法

PHP保持Session不過期的方法

*文
*文原創
2018-05-18 09:41:454671瀏覽

 

本文主要介紹了深入解說PHP Session及如何保持其不過期的方法,包括對Session回收機制的講解以及SessionId保持不變的問題的解決。希望對大家有幫助。

SESSION的實作中採用COOKIE技術,SESSION會在客戶端保存一個包含session_id(SESSION編號)的COOKIE;在伺服器端保存其他session變量,例如session_name等等。當使用者請求伺服器時也把session_id一起傳送到伺服器,透過 session_id提取所保存在伺服器端的變量,就能辨識出使用者是誰了。同時也不難理解為什麼SESSION有時會失效了。

當客戶端停用COOKIE時(點擊IE中的“工具”—“Internet選項”,在彈出的對話框裡點擊“安全性”—“自訂等級”項,將“允許每個對話COOKIE」設為停用),session_id將無法傳遞,此時SESSION失效。不過php5在linux/unix平台可以自動檢查cookie狀態,如果客戶端設定了停用,則系統自動把session_id附加到url上傳遞。 windows主機則無此功能。

php中文網學習專題php session(包含圖文、影片、案例)

Session常見函數及用法?
Session_start() :開始一個會話或傳回已經存在的會話。
說明:這個函數沒有參數,且回傳值都是true。如果你使用基於cookie的session(cookie-based sessions),那麼在使用Session_start()之前瀏覽器不能有任何輸出,否則會發生以下錯誤:
Warning: Cannot send session cache limiter - headers already sent (output started at /usr/local/apache/htdocs/cga/member/1.php:2)…………

你可以在php.ini裡啟動session.auto_start=1,這樣就不需要每次使用session之前都要呼叫session_start()。但啟用該選項也有一些限制,如果確實啟用了 session.auto_start,則不能將物件放入會話中,因為類別定義必須在啟動會話之前載入以在會話中重建物件。
請求結束後所有註冊的變數都會被序列化。已註冊但未定義的變數被標記為未定義。在之後的存取中這些變數也未被會話模組定義,除非使用者以後定義它們。

警告: 有些類型的資料不能被序列化因此也不能保存在會話中。包括 resource 變數或有循環引用的物件(即某物件將一個指向自己的參考傳遞給另一個物件)。

註冊SESSION變數 :
PHP5使用$_SESSION[‘xxx']=xxx註冊SESSION全域變數。和GET,POST,COOKIE的使用方法相似。
注意:session_register(),session_unregister ,session_is_registered在php5下不再使用,除非在php.ini裡把register_globle設為on,不過出於安全考慮,強烈建議關閉register_globle。 HTTP_SESSION_VARS也不主張使用了,官方建議用$_SESSION取代之。例如:

    Page1.php

  <?php
  Session_start(); //使用SESSION前必须调用该函数。

  $_SESSION[‘name&#39;]=”我是黑旋风李逵!”; //注册一个SESSION变量

  $_SESSION[‘passwd&#39;]=”mynameislikui”;
  $_SESSION[‘time&#39;]=time();
  echo &#39;
  通过COOKIE传递SESSION&#39;; //如果客户端支持cookie,可通过该链接传递session到下一页。

  echo &#39;
  . SID . &#39;">通过URL传递SESSION&#39;;//客户端不支持cookie时,使用该办法传递session.

  ?>

    Page2.php

  <?php
  session_start();
  echo $_SESSION[&#39;name&#39;]; //

  echo $_SESSION[&#39;passwd&#39;]; //

  echo date(&#39;Y m d H:i:s&#39;, $_SESSION[&#39;time&#39;]);
  echo &#39;
  返回山一页&#39;;
  ?>

有兩種方法傳遞一個會話ID:

  1. #cookie

  2. URL 參數

會話模組支援這兩種方法。 cookie 較最佳化,但由於不總是可用,也提供替代的方法。第二種方法直接將會話 ID 嵌入到 URL 中間去。

PHP 可以透明地轉換連接。除非是使用 PHP 4.2 或更新版本,需要在編譯 PHP 時手動啟動。在 Unix 下,用 --enable-trans-sid 配置選項。如果此組態選項和執行時間選項 session.use_trans_sid 都啟動(修改php.ini),相對 URI 將自動修改為包含會話 ID。

session_id
session_id() 用來設定或取得目前session_id。 php5中既可以使用session_id(),也可以透過附加在url上的SID來取得目前會話的session_id和session_name。
如果session_id()有具體指定值的話,將會取代目前的session_id值。使用函數前必須啟動會話:session_start();
當我們使用session cookies時,如果指定了一個session_id()值,每次啟動session_start()都會往客戶端發送一個cookie值。不論當前session_id是否與指定值相等。
session_id()如果沒有指定值,則傳回目前session_id();目前會話沒有啟動的話,則傳回空字串。

檢查session是否存在?
在以往的php版本中通常使用session_is_register()檢查session是否存在,如果您使用$_SESSION[‘XXX']=XXX來註冊會話變量,則session_is_register()函數不再起作用。你可以使用
isset($_SESSION[‘xxx'])來替代。

更改session_id session_regenerate_id() 更改成功則回傳true,失敗則回傳false。
使用函數可以為目前session更改session_id,但不改變目前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() 返回当前session的name或改变当前session的name。如果要改变当前session的name,必须在session_start() 之前调用该函数。注意:session_name不能只由数字组成,它至少包含一个字母。否则会在每时每刻都生成一个新的session id.
session改名示例:

$previous_name = session_name("WebsiteID");
echo "新的session名为: $previous_name
";
?>

如何删除session?
1、unset ($_SESSION['xxx']) 删除单个session,unset($_SESSION['xxx']) 用来unregister一个已注册的session变量。其作用和session_unregister()相同。 session_unregister()在PHP5中不再使用,可将之打入冷宫。
unset($_SESSION) 此函数千万不可使用,它会将全局变量$_SESSION销毁,而且还没有可行的办法将其恢复。用户也不再可以注册$_SESSION变量。
2、$_SESSION=array() 删除多个session
3、 session_destroy()结束当前的会话,并清空会话中的所有资源。。该函数不会unset(释放)和当前session相关的全局变量 (globalvariables),也不会删除客户端的session cookie.PHP默认的session是基于cookie的,如果要删除cookie的话,必须借助setcookie()函数。
返回值:布尔值。
功能说明:这个函数结束当前的session,此函数没有参数,且返回值均为true

session_unset() 如果使用了$_SESSION,则该函数不再起作用。由于PHP5必定要使用$_SESSION,所以此函数可以打入冷宫了。

下面是PHP官方关于删除session的案例:

  <?php
  // 初始化session.

  session_start();
  /*** 删除所有的session变量..也可用unset($_SESSION[xxx])逐个删除。****/
  $_SESSION = array();
  /***删除sessin id.由于session默认是基于cookie的,所以使用setcookie删除包含session id的cookie.***/
  if (isset($_COOKIE[session_name()])) {
  setcookie(session_name(), &#39;&#39;, time()-42000, &#39;/&#39;);
  }

// 最后彻底销毁session.

  session_destroy();
  ?>

由此我们可以得出删除Session的步骤:

  1. session_start()

  2. $_SESSION=array()/unset($_SESSION['xxx'])

  3. session_destroy()

解决PHP Session不过期以及SessionId保持不变的问题

session 回收机制:
 
PHP采用Garbage Collection process对过期session进行回收,然而并不是每次session建立时,都能够唤起 ‘garbage collection' process ,gc是按照一定概率启动的。这主要是出于对服务器性能方面的考虑,每个session都触发gc,浏览量大的话,服务器吃不消,然而按照一定概率开启gc,当流览量大的时候,session过期机制能够正常运行,而且服务器效率得到节省。细节应该都是多年的经验积累得出的。
三个与PHP session过期相关的参数(php.ini中):

  1. session.gc_probability = 1

  2. session.gc_pisor = 1000

  3. session.gc_maxlifetime = 1440

gc启动概率 = gc_probability / gc_pisor = 0.1%
session过期时间 gc_maxlifetime 单位:秒 
当web服务正式提供时,session过期概率就需要根据web服务的浏览量和服务器的性能来综合考虑session过期概率。为每个session都开启gc,显然是不明智的,感觉有点“碰运气”的感觉,要是访问量小命中几率就小。我在本机测试过程中,几乎都没有被命中过,sessionid几天都不变,哪怕机器重启。测试过程中,这个过期概率值要设置大一点命中几率才高点。
通过修改php配置文件的过期概率值,可以“碰运气”式的设置session过期,那有没有更好的办法呢?

下面写的这个session类可以彻底解决session不过期以及sessionid不变的问题。

<?php
 /**
 * 扩展Session类(简单封装)
 * 
 * @author slimboy
 *
 */
class Session { 
 
   /**
   * 初始化
   */
  static function _init(){ 
    ini_set(&#39;session.auto_start&#39;, 0); 
    //Session::start(); 
   } 
   
   /**
   * 启动Session
   */
  static function start() { 
    session_start(); 
  } 
 
   /**
   * 设置Session
   * 
   * @param $name Session名称
   * @param $value 值
   * @param $time 超时时间(秒)
   */
  public static function set($name,$value,$time){ 
    if(empty($time)){ 
      $time = 1800; //默认值 
     } 
    $_SESSION[$name] = $value; 
    $_SESSION[$name.&#39;_Expires&#39;] = time() + $time; 
  } 
   
   /**
   * 获取Session值
   * 
   * @param $name Session名称
   */
  public static function get($name){ 
    //检查Session是否已过期 
     if(isset($_SESSION[$name.&#39;_Expires&#39;]) && $_SESSION[$name.&#39;_E
 xpires&#39;]>time()){ 
      return $_SESSION[$name]; 
    }else{ 
      Session::clear($name); 
      return null; 
    } 
  } 
   
    
   /**
   * 设置Session Domain
   * 
   * @param $sessionDomain 域
   * @return string
   */
  static function setDomain($sessionDomain = null) { 
    $return = ini_get(&#39;session.cookie_domain&#39;); 
    if(!empty($sessionDomain)) { 
      ini_set(&#39;session.cookie_domain&#39;, $sessionDomain);//跨
 域访问Session 
     } 
    return $return; 
  } 
   
    
   /**
   * 清除某一Session值
   * 
   * @param $name Session名称
   */
  static function clear($name){ 
    unset($_SESSION[$name]); 
    unset($_SESSION[$name.&#39;_Expires&#39;]); 
  } 
   
    
   /**
   * 重置销毁Session
   */
  static function destroy(){ 
    unset($_SESSION); 
    session_destroy(); 
  } 
   
    
   /**
   * 获取或设置Session id
   */
  static function sessionid($id=null){ 
    return session_id($id); 
  } 
 
}
?>
简单调用:
 
<?php
  //设置session 
  Session::set(&#39;UserId&#39;, $userid, 3600); 
  //读取session
  $userId = Session::get(&#39;UserId&#39;);
?>

相关推荐:

php Session的简介

PHP高级教程:PHP Cookies

php Cookies操作类(附源码)

 

以上是PHP保持Session不過期的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn