PHP中怎樣保持SESSION不到期 原理及方案介紹_PHP

來源:互聯網
上載者:User
關鍵字 php session到期
PHP中如何保持SESSION以及由此引發的一些思考 最近的一個項目,裡面有一個比較大的表單,使用者完成它需要很多時間,很多使用者花了千辛萬苦完成之後,一提交發現SESSION到期,系統退出了,所以引起了研究如何設定SESSION以及保持SESSION線上的需要,下面是一些心得體會。

什麼是SESSION?
按照WIKI的解釋,SESSION是存在於兩個通訊裝置間的互動資訊,在某一時間建立,經過一定的時間後失效。常見的SESSION有:TCP SESSION、WEB SESSION(HTTP SESSION)、LOGIN SESSION等。

根據OSI模型中,會話實現的位置不同,SESSION主要分為幾種,一種是應用程式層會話,包括WEB SESSION(HTTP SESSION)和telnet遠程登入session;會話層實現的,包括Session Initiation Protocol(SIP)和Internet Phone Call;在傳輸層實現的有TCP SESSION。

本文主要討論WEB SESSION,其一般有兩種:用戶端SESSION和伺服器端SESSION,後一種最常見的屬於Java Beans提供的。

SESSION是做什麼的?
在電腦領域,特別是網路方面,SESSION使用的特別廣泛,也可以稱為是對話(Dialogue)、會話等,一般是指在兩個通訊裝置間儲存的狀態,有時也發生在使用者和電腦之間(Login SESSION)。

區別於無狀態的通訊,SESSION通常用來儲存通訊狀態,因此通訊的雙方至少有一方需要儲存SESSION的記錄,從而實現兩者間的通訊。

SESSION(WEB SESSION)是怎麼實現的?
瀏覽器和伺服器之間進行HTTP通訊時,通常會包含一個 HTTP Cookie 來標識狀態,通常會有一個唯一的 SESSIONID ,SESSION通常記錄著使用者的一些驗證資訊和層級。

在幾中程式設計語言中最常用的Http Session Token是,JSESSIONID(JSP),PHPSESSID(PHP),ASPSESSIONID(ASP),這個標識通常由雜湊函數產生,能夠 唯一表示這個使用者的身份,在伺服器和用戶端通訊時,作為GET或者POST的參數儲存在用戶端。

SESSION的實現方式通常有兩種,伺服器端SESSION和用戶端SESSION,兩種方式各有優缺點。

伺服器端SESSION實現容易並且效率比較高,但是遇到負載平衡或者高可用性需求的時候,處理起來就比較困難,對於那種內生系統不存在存放裝置的時候, 也是停用。負載平衡可以通過共用檔案系統或者強制客戶只能登入到一台伺服器上來實現,但是這樣會降低效率。對於沒有儲存的裝置,也可以通過使用 RAM(參考參考資料6)來解決伺服器端SESSION的實現,這種方法這對哪些用戶端連結有限的系統有效(諸如路由或者存取點裝置)。

用戶端SESSION的使用可以解決伺服器端SESSION的一些問題,比如避免了負載平衡的演算法等,但是同時也會產生一些自身的問題。用戶端 SESSION使用Cookie和加密技術來在不同的請求間儲存狀態。在每一個動態網頁面結束後,會統計當前的SESSION,並把它發回用戶端。每次成功 請求後,會把cookie再發送到伺服器端,來讓伺服器“記起”這個使用者的身份。用戶端SESSION最重要的問題就是安全問題,一旦cookie被劫持 或者篡改了,使用者的資訊的安全性就喪失了。

PHP中如何設定SESSION?
搭建好PHP的開發環境後,通過phpinfo()可以查看到與SESSION有關的部分包括:
SESSION模組,在PHP V5.2.9版本中,一共有25個變數。其中,平時設定中常會用到的幾個有:
複製代碼 代碼如下:
session.cookie_lifetime 設定儲存SESSIONID的cookie到期時間
session.name SESSION的COOKIE名稱,預設為PHPSESSID
session.save_handler SESSION的儲存方式,預設為FILE
session.save_path Fedora下面預設儲存在/var/lib/php/session
session.gc_probability
session.gc_divisor
session.gc_maxlifetime 這三個選項用來處理GC機制發生的機率
session.cache_limiter (nocache,private,private_no_expire,public)
session.cache_expire 這兩個選項是用來緩衝SESSION的頁面

先來考慮第一個問題,SESSION多久會到期,他是如何到期的?如果要在PHP程式中使用SESSION,一定要先引用 session_start(),這個函數一執行,就會在SESSION的儲存目錄(如果使用了file handler)產生一個SESSION檔案,裡面內容是空的,同時瀏覽器會見裡一個name為PHPSESSID的cookie,裡面儲存著一個 hash出來的SESSION的名字。

SESSION的到期依賴於一個記憶體回收機制(Garbage Collection),SESSION建立後作為一個檔案存放在伺服器上,用戶端指令碼每訪問一次SESSION中的變數,SESSION檔案的訪問時間 就會進行更新。每次訪問都是根據用戶端儲存的SESSIONID去請求伺服器中儲存的唯一的SESSION,當用戶端的cookie到期後,就無法知道要 訪問的是哪一個SESSION,儘管此時伺服器上的SESSION檔案還沒有被到期收回,這樣就會造成伺服器資源的浪費。

但是同時,如果我們希望使用者的session馬上到期的話,我們就可以通過設定cookie的辦法來實現。SESSION的回收是在每次訪問頁面的時候進 行的,回收的機率由session.gc_probability,session_gc_divisor指定,預設士1/100。如果設定為1,則每次 超過了SESSION的生存周期去訪問的話,SESSION一定會被回收。

兩種需求:
1、保持SESSION不到期或延長SESSION到期時間;
2、使SESSION立即到期。

1、保持SESSION不到期和延長SESSION到期時間非常必要,特別是在內部應用系統中或者有很大的表單的時候。想想你的老闆在填寫一個表單,剛好 碰上午飯時間,留著這個表單等吃飯回來,填寫完剩餘的內容,提交後他看到什麼,一般來說都是一個登入介面。想要提高使用者體驗,關鍵是要讓老闆的表單不出問 題,我們就必須延長SESSION的生存周期。

保持SESSION不到期和延長SESSION到期時間,可以通過設定session.gc_maxlifetime來實現,不過首先需要保證用戶端的 cookie不會在gc執行回收之前失效。通過設定一個較長的gc_maxlifetime可以實現延長session的生存周期,可是對於不是所有請求 都會保持很久的應用來說,這麼做對於伺服器配置顯然不是一個最佳的選擇。
我們知道SESSION的回收機制是根據SESSION檔案的最後訪問時間來判斷的,如果超過了maxlifetime,則根據回收機率進行回收。所以我們只需要週期性去訪問一下SESSION就可以了,而這可以通過重新整理頁面來實現,根據這個思路,解決的方法就有了。

通過JS週期性去訪問頁面;
利用Iframe週期性重新整理頁面;

直接利用程式發送HTTP請求,這樣就可以避免在頁面中嵌入其他的元素;

下面是利用JS發送請求實現的保持SESSION不到期的實現方法,這樣我們就只需要在需要SESSION保持長時間的頁面(比如大表單頁面)。
複製代碼 代碼如下:



其中URL後加入一個隨機數是為了避免這個連結的請求被瀏覽器緩衝。

2、使SESSION立即到期的方法就比較多了,我們可以session_destroy(),也可以用上面的思路,請求一個session_destroy的頁面。

SESSION安全嗎?
PHP的手冊中明確寫出:SESSION並不能保證儲存在SESSION中的資訊一定只能被他的建立者所看到。

如果想要安全的處理一些遠端操作,那麼HTTPS是唯一的選擇。最基本的,不要認為一個使用者資訊在SESSION中存在就認為這個使用者一定就是他本人, 雖然SESSION中的資訊會給你他已經經過了使用者名稱和密碼驗證的假象。所以,如果需要做一些修改密碼或者類似的事情的時候,讓使用者重新輸入密碼是一個比 較好的選擇。

早期的Apache版本並沒有採用COOKIE的方式來儲存PHPSESSID,而是採用的URL-rewrite,也就是每個URL後面都會加上 PHPSESSID=來表明它屬於那個啟用的SESSION,新版的Apache已經將這個屬性設定為預設關閉。
複製代碼 代碼如下:
session.use_trans_id = 0;

所以從這個意義上來講,延長SESSION的時間過長或者保持SESSION一直線上對於安全來說始終不是一件好事情。終極的解決辦法就是使用者提交跳轉到 登入視窗,登入後又能夠回到填寫頁面,並且所有的資料都還在。這個的實現方式現在用Ajax來解決應該沒什麼困難,每隔一定時間就把當前的使用者資料 POST到一個儲存位置,不管是XML或者JSON。

拾遺:
對於用戶端不支援JavaScript的情況可以採用的方法:
1、寫一個浮層,顯示在最頂層,如果使用者未禁用JS,則讓浮層消失;
2、將所有的INPUT都設定為disable,然後再用JS設定為enabled;
以上這兩種方式都是在JS被禁用的時候,所有功能都不能用,如何在JS被禁用的情況下使我們的應用仍然正常工作,這個貌似就比較困難。實現這個的所花的時間和所收到的效果大家要權衡一下。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.