2008-09-16 86 views
24

我最近經常做的一件事是在任務開始時檢索一些數據並存儲它在$ _SESSION ['myDataForTheTask']

現在看起來很方便,但我不知道使用這種方法的性能,安全風險或類似情況。這是由具有更多專業知識的程序員定期完成的事情,還是更多的業餘事情?

例如:

if (!isset($_SESSION['dataentry'])) 
{ 
    $query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=" . mysql_real_escape_string($_GET['wave_id']); 
    $result_taskinfo = $db->query($query_taskinfo); 
    $row_taskinfo = $result_taskinfo->fetch_row(); 

     $dataentry = array("pcode" => $row_taskinfo[0], "modules" => $row_taskinfo[1], "data_id" => 0, "wavenum" => $row_taskinfo[2], "prequest" => FALSE, "highlight" => array()); 

     $_SESSION['dataentry'] = $dataentry; 
} 
+3

您的SQL查詢容易受到SQL注入攻擊。例如,某人可以放置'?wave_id = wave_id',查詢將選擇所有行。 (這在DELETE,INSERT和UPDATE查詢中更糟糕。)在這種情況下,您應該編寫代碼以確保它是一個數字,最簡單的方法是intval() – 2008-09-16 22:20:44

回答

16

那麼會話變量實際上是唯一一種讓訪問者在網站上訪問這些變量的唯一方式(也可能是最有效的方法)之一,用戶無法編輯它們(除了代碼中的漏洞或PHP解釋器中的漏洞),因此它們相當安全。

這是一種存儲用戶可以更改設置的好方法,因爲您可以在會話開始時從數據庫讀取一次設置,並且可以在整個會話中使用這些設置,您只需要創建更多的數據庫如果設置發生變化,則會發生調用,當然,正如您在代碼中所顯示的那樣,查明設置是否已存在或是否需要從數據庫中提取這些設置是微不足道的。

我想不出安全地存儲臨時變量的任何其他方式(因爲Cookie可以很容易地進行修改,這將是在大多數情況下,不良),所以$ _SESSION將要走

+3

「它們相當安全」僅當它是專用服務器時纔是真實的。共享託管在同一臺機器上的其他用戶可以訪問php會​​話數據。 – Jacco 2009-04-20 15:44:05

1

$ _SESSION項目存儲在會話中,這是在默認情況下,保留在磁盤上。不需要像你一樣製作自己的數組並將其填入「數據入口」數組條目中。你可以使用$ _SESSION ['pcode'],$ _SESSION ['modules']等等。

就像我說過的,會話存儲在磁盤上,會話指針存儲在cookie中。用戶因此不能容易地查看會話數據。

+1

只需使用多維數組 $ _SESSION [ mystuff'] ['mydata'] ='blah'; – conmulligan 2008-09-16 22:31:41

+0

@conmulligan:當然,但除了你放在那裏的東西之外,沒有什麼會進入會議。您可能會將$ _SESSION與$ _SERVER混淆。 – nsayer 2008-09-17 22:24:59

0

我使用這種方法很公平,我沒有看到任何問題。與Cookie不同,數據不存儲在客戶端,這通常是一個很大的錯誤。

就像任何事情一樣,小心你總是在清理用戶輸入,特別是如果你將用戶輸入放入$ _SESSION變量,然後在SQL查詢中使用該變量。

3

在決定存儲臨時數據的位置時,您需要考慮幾個因素。會話存儲對於特定於單個用戶的數據非常有用。如果您發現默認的基於文件的會話存儲處理程序效率低下,則可以使用後端數據庫或memcache類型來實現其他內容。有關更多信息,請參閱session_set_save_handler

我發現將常見數據存儲在用戶會話中是一種不好的做法。有更好的地方可以存儲將被多個用戶頻繁訪問的數據,並通過將這些數據存儲在會話中,您將爲每個需要此數據的用戶複製數據。在你的例子中,你可能爲這個波形數據建立了一個不同類型的存儲引擎(基於wave_id),這個數據不是專門針對用戶會話的。通過這種方式,您可以將數據向下拖動一次,然後將其存儲在某個用戶可以訪問數據的地方,而無需再次拖動。

1

IMO,它是完全可以接受的東西存儲在會話中。這是使數據持久化的好方法。在許多情況下,它也比將所有內容存儲在Cookie中更安全。以下是一些問題:

  • 某人劫持一個會話是可能的,所以如果您打算使用它來跟蹤用戶授權,請注意。閱讀this瞭解更多信息。
  • 它可能是一個非常懶惰的方式來保持數據。不要只是將所有內容都放在會話中,以便以後不必查詢。
  • 如果您打算在會話中存儲對象,那麼在下次請求啓動會話之前,需要將其類文件包含在內,否則您需要配置自動加載器。
2

如果您正在自己的服務器上運行,或者在沒有人可以監聽服務器上的文件/內存的環境中運行,則會話數據是安全的。它們存儲在服務器上,只是發送給客戶端的身份識別碼。問題是,如果其他人可以抓取cookie並冒充其他人,當然。使用HTTPS並確保不要將會話ID放入URL中,這樣可以讓您的用戶免於大部分問題的困擾。 (如果您不小心,XSS可能仍然用於抓取cookie,請參閱Jeef Atwoods post on this。)

至於要存儲在會話變量中的內容如果要在其他頁面上再次引用它,就像購物籃一樣,但如果它只是用於生成此頁面結果的臨時數據,就不會放在那裏,就像當前查看帖子的標籤列表一樣。會話是針對每個用戶的持久數據。

0

這是一個相當常見的事情,會話通常會比連續的數據庫命中更快。他們也相當安全,因爲PHP開發人員努力工作以防止會話劫持。

唯一的問題是,您需要記住在某些更改時重建會話條目。而且,如果擁有該會話的用戶以外的任何用戶更改了此密鑰,則無法通知系統刷新該會話密鑰。可能不是什麼大不了的,但你應該注意的事情。

4

我一直使用會話變量來爲用戶存儲信息。我沒有看到任何性能問題。會話數據根據Cookie進行提取(如果您關閉了Cookie,則會提供PHPSESSID)。我不認爲它比任何其他基於cookie的認證都更具安全風險,並且可能比將實際數據存儲在用戶cookie中更安全。

只是爲了讓你雖然知道,你有你的SQL語句的安全問題:

SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".$_GET['wave_id']; 

你應該從來,我再說一遍從未,採取用戶提供的數據,並用它來運行SQL聲明沒有先清理它。我會把它用引號括起來,並添加功能mysql_real_escape_string()。這將保護你免受大多數攻擊。所以,你的行會看起來像:

$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id='".mysql_real_escape_string($_GET['wave_id'])."'"; 
+0

謝謝!這個樁溢出讓我以驚人的速度學習,我很驚訝。 – markus 2008-09-16 22:31:01

2

另一種方式的方式改善輸入驗證是投_GET [「wave_id」]變量:

$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".(int)$_GET['wave_id']." LIMIT 1"; 

我假定wave_id是整數,並且僅存在一個答案。

1

我發現會話是非常有用的,但有幾個注意事項:

1)這PHP可以存儲您的會話中可能對其他訪問的TMP文件夾或其他目錄用戶在您的服務器上。您可以通過轉到php.ini文件來更改存儲會話的目錄。

2)如果你正在建立,需要您可能希望將它發送到會議之前對數據進行加密,並解密使用它非常嚴密的安全措施較高的價值體系。注意:這可能會產生太多開銷,具體取決於您的流量/服務器容量。

3)我發現session_destroy();不會立即刪除會話,您仍然需要等待PHP垃圾收集器清理會話。您可以更改垃圾收集器在php.ini文件中運行的頻率。但仍似乎並不十分可靠,更多信息http://www.captain.at/howto-php-sessions.php

5

$ _SESSION機構會使用Cookie。

在Firefox(也許是新的IE瀏覽器,我沒有檢查自己)的情況下,這意味着會話在打開的標籤之間共享。這不是你默認的預期。這意味着會話不再是「單個窗口/用戶專用的東西」。

例如,如果你已經打開了兩個標籤來訪問您的網站,使用第一個選項卡不是記錄爲根,你會在另外一個獲得root權限。

那可真是不方便,特別是如果你的代碼的電子郵件客戶端或其他什麼東西(如網上商店)。在這種情況下,您必須手動管理會話或在URL中引入不斷重新生成的密鑰或執行其他操作。

1

你可能想考慮一下這是怎樣的REST-ful?

即見「溝通無狀態」段落「A Brief Introduction to REST」 ......

「REST授權該締約國要麼 變成資源狀態,或保留在 客戶端。換句話說,服務器 不應該保留某種 通信狀態對於任何 客戶它超出 單個請求傳達的。」

(或任何在維基百科上的其他鏈接,REST的)

所以你的情況,在「wave_id」是一個明智的資源得到的,但你真的希望將其存儲在SESSION?當然,memcached是緩存對象資源的解決方案嗎?

1

使用會議的其他一些缺點:後的session.gc_maxlifetime閒置

  1. $_SESSION數據將到期。
  2. 您必須記得爲每個將使用會話數據的腳本調用session_start()
  3. 通過在多個服務器上進行負載均衡來擴展網站可能是一個問題,因爲用戶每次都需要定向到同一個服務器。用「粘滯會話」解決這個問題。
0

$ _SESSION是在安全性非常有用,因爲它是一個服務器端的方式來存儲信息,而用戶是活躍在您的網頁,因此很難破解,除非您的實際php文件或服務器有被利用的弱點。一個非常好的實現是存儲變量以確認用戶已登錄,並且只允許在確認登錄後執行操作。