1 需求
按照用途分類:
- 會話(會話ID和會話令牌 二選一)
- 會話ID:服務器側自動生成,自動存儲在cookie中,需要在服務器側存儲
- 會話令牌:服務器側手動生成,手動存儲在cookie中,不需要再服務器側存儲
- CSRF
- CSRF令牌:
按照存儲位置分類:
- 服務器側
- $_SESSION
- 瀏覽器側
- cookie
- 隱藏控件
2 語法
3 示例
在 PHP 中,防范 CSRF(跨站請求偽造)攻擊的一種常見方法是使用令牌(token)驗證。這個令牌通常是一個隨機生成的字符串,它在表單提交時與用戶的會話(session)相關聯。下面是一個簡單的 PHP 示例,演示了如何防范 CSRF 攻擊:
- 生成 CSRF 令牌
在會話開始時,生成一個隨機的 CSRF 令牌并將其存儲在會話中。
session_start();// 生成 CSRF 令牌 if (!isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); }
- 在表單中包含 CSRF 令牌
在 HTML 表單中,將 CSRF 令牌作為隱藏字段或作為請求頭的一部分包含在內。
<form action="submit.php" method="post"> <!-- 其他表單字段 --><!-- CSRF 令牌作為隱藏字段 --> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><!-- 提交按鈕 --> <button type="submit">Submit</button> </form>
或者,你可以使用 JavaScript 將 CSRF 令牌作為請求頭的一部分發送:
// 假設你已經在某處將 CSRF 令牌存儲在 JavaScript 變量中 var csrfToken = '...'; // 從 cookie、localStorage 或其他地方獲取// 使用 AJAX 發送請求時,將 CSRF 令牌作為請求頭的一部分發送 $.ajax({ url: 'submit.php', type: 'POST', data: { /* 其他數據 */ }, headers: { 'X-CSRF-Token': csrfToken }, success: function(response) { // 處理響應 } });
- 驗證 CSRF 令牌
在服務器端,驗證接收到的 CSRF 令牌是否與會話中的令牌匹配。
session_start();
// 檢查是否提交了 CSRF 令牌 if (isset($_POST['csrf_token']) && $_POST['csrf_token'] === $_SESSION['csrf_token']) { // CSRF 令牌驗證成功,處理表單數據 // ... } else { // CSRF 令牌驗證失敗,可能是 CSRF 攻擊 // 可以采取相應的措施,如記錄日志、返回錯誤消息等 die('Invalid CSRF token.'); }
如果你使用的是 AJAX 請求并通過請求頭發送 CSRF 令牌,你可以在服務器端通過?
$_SERVER['HTTP_X_CSRF_TOKEN']
?來獲取它并進行驗證。請注意,這只是一個簡單的示例,用于說明如何防范 CSRF 攻擊。在實際應用中,你可能還需要考慮其他安全措施,如使用 HTTPS 來加密通信、限制請求的來源等。
4 參考資料
CSRF 令牌(通常稱為 CSRF token)通常是在用戶會話(session)開始時生成,并在整個會話期間保持不變。這意味著,在用戶的單個會話中,CSRF 令牌是唯一的并且相同的,但不同的用戶會話或不同的瀏覽器會話會有不同的 CSRF 令牌。
這是 CSRF 令牌的一個典型實現方式:
- 當用戶首次訪問受保護的頁面或應用時,服務器會為該用戶會話生成一個隨機的 CSRF 令牌,并將其存儲在會話數據(如 PHP 的?
$_SESSION
)中。- 同時,服務器會將這個 CSRF 令牌嵌入到發送到客戶端的頁面中,通常是通過一個隱藏的表單字段或者 cookie。
- 當用戶提交表單時,客戶端會將 CSRF 令牌包含在請求中(通常是通過表單字段或自定義的 HTTP 請求頭)。
- 服務器在接收到請求時,會檢查請求中的 CSRF 令牌是否與會話數據中的令牌匹配。如果匹配,則繼續處理請求;如果不匹配,則拒絕請求,并可能記錄一個安全事件。
由于 CSRF 令牌是在會話開始時生成的,并且通常在整個會話期間保持不變,因此服務器可以在多個請求之間驗證相同的 CSRF 令牌。這樣可以確保只有知道當前會話 CSRF 令牌的用戶(即同一瀏覽器的同一用戶會話)才能提交有效的表單請求。
然而,值得注意的是,有些實現可能會選擇在每次請求時都生成新的 CSRF 令牌。雖然這可以提供更高的安全性(因為即使 CSRF 令牌在某個時間點被泄露,它也會在很短時間內失效),但它也會增加實現的復雜性,并可能導致一些額外的問題(如需要在多個頁面之間傳遞和同步 CSRF 令牌)。因此,在大多數情況下,每個會話一個 CSRF 令牌是足夠安全的,并且更容易實現和管理。