首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

PHP Session 唯一標識符驗證機制深度解析:防重複提交與 CSRF 防護

     編輯:程式設計綜合問答

代碼片段

$_SESSION['uniqid'] = $_uniqid = sha1(uniqid(rand(), true));

核心疑問

既然 `$_SESSION['uniqid']` 與 `$_uniqid` 賦值時相等,為何驗證時還要比較兩者是否一致?`$_uniqid` 是表單隱藏域的值。

機制原理:雙重驗證模式

這不是多餘,而是經典的 同步器令牌模式(Synchronizer Token Pattern) 核心邏輯:

  1. 生成階段:伺服器生成隨機 Token,同時存入 Session 與表單隱藏域
  2. 提交階段:用戶提交表單時,隱藏域 Token 隨請求發送
  3. 驗證階段:伺服器比對 Session 中的 Token 與請求中的 Token

為何必須比較而非直接信任?

攻擊場景若不比較會發生什麼比較後的防護效果
用戶重複點擊提交後端處理多次業務邏輯(如重複扣款)第二次提交 Token 已失效/不匹配,攔截
CSRF 跨站請求偽造攻擊者構造惡意表單,受害者不知情提交攻擊者無法獲取受害者 Session 中的 Token
表單重放攻擊截獲請求重複發送一次性 Token 機制使重放失效

最佳實踐代碼

<?php
// 生成頁面時
session_start();
$token = bin2hex(random_bytes(32));  // 密碼學安全隨機數
$_SESSION['csrf_token'] = $token;
?>
<form method="POST">
    <input type="hidden" name="csrf_token" value="<?php echo $token; ?>">
    <!-- 其他表單欄位 -->
</form>

<?php
// 處理提交時
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $submitted = $_POST['csrf_token'] ?? '';
    $stored = $_SESSION['csrf_token'] ?? '';
    
    // 使用 hash_equals 防止時序攻擊
    if (!hash_equals($stored, $submitted)) {
        die('Token 驗證失敗,請重新提交');
    }
    
    // 驗證通過,執行業務邏輯
    // ...
    
    // 可選:一次性 Token,驗證後銷毀
    unset($_SESSION['csrf_token']);
}
?>

進階建議

  • 使用 random_bytes() 而非 uniqid(rand()),後者熵值不足
  • 採用 hash_equals() 恆定時間比較,防範側通道攻擊
  • 敏感操作(轉帳、刪除)採用一次性 Token,一般查詢可複用
  • 結合 SameSite Cookie 屬性(Lax/Strict)提供纵深防禦
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved