2015-07-20 199 views
2

我在一個半月前開始學習PHP,並開始通過嘗試創建自己的非常簡單的CMS來學習如何構建基本的CRUD腳本與mysql數據庫進行交互等等。登錄,用戶身份驗證,會話和csrf令牌

我目前正在構建我的CMS的私人管理部分的登錄表單,通過這樣做我想了解PHP中的基本安全性。

我想對用戶身份驗證進行一些基礎研究,但我遇到的解釋通常包含有關我沒有完全理解的最佳安全實踐的信息。

所以,我查找了更多關於我不明白的小部分信息,其中包括我不熟悉的其他部分,我被拖入吸收了大量有關安全主題的信息,比如通過默默無聞的安全性,單向密碼散列,通過適當的PHP配置設置安全,防禦sql注入,php注入,會話劫持等。

我無法實現所有這些,因爲我無法真正理解這一切。

所以第一個問題是關於將用戶會話存儲在數據庫中。

我現在知道的是,如果我使用共享主機,服務器可能沒有正確配置,並且服務器存儲會話的文件夾可能會被其他人訪問。

這是我想將會話存儲在數據庫中的唯一原因嗎?

二,如何在db中存儲會話解決訪問問題?

爲了詳細說明我的困惑,我很清楚,一旦會話存儲在數據庫中,它就可以安全地從共享主機上的人身上,但是如何告訴php - 「嘿,我將我的用戶會話存儲在數據庫,從你指定的默認存儲位置排除它「?

換句話說,僅僅因爲我將會話存儲在數據庫中並不意味着服務器將它從默認存儲會話的地方排除。這是否正確?如果是,我該如何控制它?

第三,我如何實際將會話存儲在數據庫中?我假設以下過程:

session_start(); 

//Assume a user has successfully logged in 
//For better security regenerate the session on login 
$session = session_regenerate_id(); 

$data[]= $session; 

$query = $db_connection->prepare("INSERT INTO `sessions`(`session`) VALUES (?)"); 
$query->execute($data); 

這是什麼意思將會話存儲在數據庫中的最基本的形式?

繼續下一個問題。

讓我們假設我已經解決了上述問題。現在如何驗證用戶是否登錄?

通常我會做這樣的事情:

if(!isset($_SESSION['user'])) { 
    redirect_to('login.php'); 
} 

但由於用戶會話存儲在數據庫中,是它提供給我直接或者我需要首先將其拉出分貝的順序使用它?

我知道,一旦會議開始還有一個加密/散列(不知道到底哪一個是)在一個名爲PHPSESSID瀏覽器會話cookie的事實。

但是,因爲我將會話存儲在數據庫中,這意味着我正在手動控制PHP通常會自動執行的操作,這在我頭腦中的過程鏈是generate-> store-> encrypt/hash-> set會話cookie。

這個假設是否正確?

而且最後跨站點僞造請求。

我的理解是,當用戶登錄時,他會被欺騙地點擊鏈接等來複制瀏覽器的cookie,現在攻擊者擁有會話cookie並可以模擬用戶。

如何保存在一個隱藏字段我形成了CSRF令牌在這種情況下幫助嗎?

如果攻擊者劫持用戶檢查對會話令牌沒有幫助,因爲攻擊者具有有效會話的會話。

我錯過了什麼?

有在我的腦海知識差距上是如何工作的,我希望你能有所彌補這些對我來說。

+1

你在一個單獨的問題中提出了很多問題,你應該將它們隔離開來,因爲它太大而無法正確回答。 –

回答

1
  1. 這是我想將會話存儲在 數據庫中的唯一原因嗎?

該數據庫受密碼保護,會話目錄不是。毋庸置疑,大多數服務器應該保護/ tmp/session路徑(iirc),並且沒有人可以訪問它。但是,再次,您必須相當信任主機。

  1. 二,如何在db中存儲會話解決訪問問題?

參見答案#1

  • 換句話說,只是因爲我存儲在數據庫中的會話並不意味着服務器從地方排除它它默認存儲會話。這是否正確?如果是,我該如何控制它?
  • 基本上,會話用一個唯一的標識符來標識。瀏覽器發送一個帶有ID的cookie,服務器讀取cookie ID並將其引用到服務器上的配置位置。要設置保存路徑,您可以使用session_set_save_handler - 這將允許您在會話中(保存時)執行任何您想要的操作 - 例如將其保存到數據庫。見例2。

    1. 現在如何驗證用戶是否已登錄?

    **有多種方式可以確定用戶是否已登錄。一種基本方法是在會話中存儲唯一數據並將其與用戶表關聯起來。當瀏覽器發送會話ID時,服務器可以根據ID檢索數據。然後,您可以獲取這些數據並將其與用戶表交叉引用以對用戶進行身份驗證。請記住,服務器(通常)是無狀態的,意味着在頁面之間導航,服務器不會跟蹤頁面之間的用戶。因此使用會話。一個非常基本的例子,我不會使用這個,是這樣的:

    <?php 
    function isLoggedIn() { 
        if(!empty($_SESSION['user'])) { 
        $uuid = $_SESSION['user']['uuid']; // universal unique id 
        $username = $_SESSION['user']['username']; // username 
        $last = $_SESSION['user']['last']; // last use of session 
        if($last > time() - 600) { // active last 10 minutes? 
         $stmt = $db->prepare("SELECT username FROM users WHERE uuid = :uuid"); 
         $stmt->bindValue(":uuid", $uuid, PDO::PARAM_STR); 
         $user = $stmt->fetch(PDO::FETCH_ASSOC); 
         if($username == $user['username']) { // user is logged in. uuid on session matches uuid in users table 
         $_SESSION['user']['last'] = time(); 
         return true; 
         } 
        } 
        } 
    
        session_destroy(); // clear everything! 
        return false; 
    } 
    ?> 
    
  • 但由於用戶會話被存儲在數據庫中,是直接提供給我或我是否需要首先將它從數據庫中取出才能使用它?
  • 不要將用戶會話與用戶對象本身混淆。會話用於將實際的用戶和APP綁定在一起。見上面的回答&例如

  • 如何保存在一個隱藏字段我形成了CSRF令牌在這種情況下幫助嗎?
  • 當你在你的形式CSRF令牌,你也有服務器...含義與表單的頁面加載時,會生成並存儲在一個會話的一個CSRF令牌上的CSRF令牌特定用戶。請記住,擁有會話cookie的用戶沒有數據 - 只是標識符。該表單還會有一個隱藏字段,例如csrf_token。在POST上,服務器將比較帖子令牌和會話。它也將重置/清除令牌,以便它永遠不會再次被髮布/使用。這些令牌應該是唯一的..通常像md5(time())這樣的工作很好。如果令牌不匹配或丟失,可能會發生攻擊。這裏採取的最佳措施是使用新的CSRF令牌再次顯示錶單。