最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PHP中四種主流Token實現(xiàn)方案

 更新時間:2026年01月29日 10:00:35   作者:云游云記  
Token 機制廣泛應(yīng)用于身份驗證、防止 CSRF 攻擊、接口鑒權(quán)等場景,在 PHP 中,主流實現(xiàn)方案均圍繞 生成唯一標(biāo)識 + 存儲驗證 + 有效期控制三大核心思路展開,本文梳理了 4 種主流實現(xiàn)方式,便于快速選型和實踐,需要的朋友可以參考下

Token 機制廣泛應(yīng)用于身份驗證、防止 CSRF 攻擊、接口鑒權(quán)等場景。在 PHP 中,主流實現(xiàn)方案均圍繞 生成唯一標(biāo)識 + 存儲驗證 + 有效期控制三大核心思路展開。本文梳理了 4 種主流實現(xiàn)方式,便于快速選型和實踐。

方案 1:基于 Session 的 Token 實現(xiàn)

核心原理

利用 PHP 內(nèi)置 Session 機制,將 Token 存儲在服務(wù)端 Session 中,客戶端僅保存 SessionID(通常通過 Cookie)。每次請求時,服務(wù)端驗證 Token 是否匹配。

實現(xiàn)代碼

<?php
// 初始化Session
session_start();
 
/**
 * 生成并存儲Token
 */
function generateSessionToken() {
    $token = bin2hex(random_bytes(16));
    $_SESSION['csrf_token'] = $token;
    $_SESSION['csrf_token_expire'] = time() + 3600; // 1小時有效期
    return $token;
}
 
/**
 * 驗證Session Token
 */
function verifySessionToken($token) {
    if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_expire'])) {
        return false;
    }
    if (time() > $_SESSION['csrf_token_expire']) {
        unset($_SESSION['csrf_token'], $_SESSION['csrf_token_expire']);
        return false;
    }
    $isValid = hash_equals($_SESSION['csrf_token'], $token);
    if ($isValid) {
        unset($_SESSION['csrf_token'], $_SESSION['csrf_token_expire']);
    }
    return $isValid;
}
 
// 示例
$token = generateSessionToken();
echo '<input type="hidden" name="csrf_token" value="'.$token.'">';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $clientToken = $_POST['csrf_token'] ?? '';
    if (verifySessionToken($clientToken)) {
        echo 'Token驗證通過,執(zhí)行業(yè)務(wù)邏輯';
    } else {
        echo 'Token無效或已過期';
    }
}
?>

優(yōu)缺點

優(yōu)點缺點
實現(xiàn)簡單,依賴 PHP 原生 Session依賴 Cookie,客戶端禁用 Cookie 則失效
Token 存儲在服務(wù)端,安全性高分布式部署需配置 Session 共享,如 Redis
支持服務(wù)端主動銷毀 Token占用服務(wù)器內(nèi)存(Session 默認存儲在文件/內(nèi)存)

方案 2:基于 JWT(JSON Web Token)的 Token 實現(xiàn)

核心原理

JWT 是一種 無狀態(tài) Token 方案,由 Header、Payload、Signature 三部分組成。Token 存儲于客戶端(如 LocalStorage/Cookie),服務(wù)端僅通過簽名校驗其合法性和完整性。

前置條件

需安裝 JWT 擴展,推薦使用 firebase/php-jwt:

實現(xiàn)代碼

<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey = 'your_strong_secret_key';
$algorithm = 'HS256';

/**
 * 生成JWT Token
 */
function generateJwtToken($payload = []) {
    global $secretKey, $algorithm;
    $defaultPayload = [
        'iat' => time(),
        'exp' => time() + 3600,
    ];
    $payload = array_merge($defaultPayload, $payload);
    return JWT::encode($payload, $secretKey, $algorithm);
}

/**
 * 驗證JWT Token
 */
function verifyJwtToken($token) {
    global $secretKey, $algorithm;
    try {
        $decoded = JWT::decode($token, new Key($secretKey, $algorithm));
        return (array)$decoded;
    } catch (Exception $e) {
        echo 'Token驗證失?。? . $e->getMessage();
        return false;
    }
}

// 示例
$userPayload = ['uid' => 1001, 'username' => 'test_user'];
$jwtToken = generateJwtToken($userPayload);
echo '生成的JWT Token:' . $jwtToken . '
';

$clientToken = $_GET['token'] ?? '';
$decodedData = verifyJwtToken($clientToken);
if ($decodedData) {
    echo 'Token驗證通過,用戶ID:' . $decodedData['uid'];
} else {
    echo 'Token無效';
}
?>

優(yōu)缺點

優(yōu)點缺點
無狀態(tài),分布式友好Token 無法主動銷毀,僅能等過期(可用黑名單彌補)
支持跨域、跨平臺負載信息 Base64 編碼,不可存儲敏感數(shù)據(jù)
傳輸體積小,可自定義數(shù)據(jù)密鑰泄露風(fēng)險高,需嚴格保管
不依賴 Cookie,兼容性好過期時間固定,需重新簽發(fā)才能調(diào)整

方案 3:基于 Redis 的 Token 實現(xiàn)

核心原理

Token 作為 Key,用戶信息/過期時間作為 Value 存儲在 Redis。利用 Redis 過期鍵特性自動管理 Token 有效期,驗證時查詢 Redis 是否存在該 Token 且未過期。

前置條件

需安裝 PHP Redis 擴展,并配置 Redis 連接。

實現(xiàn)代碼

<?php
function initRedis() {
    $redis = new Redis();
    try {
        $redis->connect('127.0.0.1', 6379);
        // $redis->auth('your_redis_password');
        return $redis;
    } catch (Exception $e) {
        echo 'Redis連接失?。? . $e->getMessage();
        return null;
    }
}

function generateRedisToken($uid, $expire = 3600) {
    $redis = initRedis();
    if (!$redis) return false;
    $token = md5($uid . time() . random_bytes(16));
    $tokenKey = 'token:' . $token;
    $redis->setex($tokenKey, $expire, $uid);
    return $token;
}

function verifyRedisToken($token) {
    $redis = initRedis();
    if (!$redis) return false;
    $tokenKey = 'token:' . $token;
    $uid = $redis->get($tokenKey);
    if ($uid) {
        $redis->expire($tokenKey, 3600); // 滑動有效期
        return (int)$uid;
    }
    return false;
}

function destroyRedisToken($token) {
    $redis = initRedis();
    if (!$redis) return false;
    $tokenKey = 'token:' . $token;
    return $redis->del($tokenKey) > 0;
}

// 示例
$token = generateRedisToken(1001);
echo 'Redis Token:' . $token . '<br>';

$clientToken = $_POST['token'] ?? '';
$uid = verifyRedisToken($clientToken);
if ($uid) {
    echo 'Token驗證通過,用戶ID:' . $uid;
} else {
    echo 'Token無效或已過期';
}

// destroyRedisToken($clientToken);
?>

優(yōu)缺點

優(yōu)點缺點
支持分布式、集群部署依賴 Redis,增加系統(tǒng)復(fù)雜度
可主動銷毀 Token,安全性高Redis 性能或容災(zāi)需關(guān)注
支持滑動有效期需處理 Redis 連接異常,代碼需容錯
不依賴 Cookie,兼容性好性能略低于 Session/JWT(需網(wǎng)絡(luò) IO)

方案 4:基于數(shù)據(jù)庫(MySQL)的 Token 實現(xiàn)

核心原理

將 Token、用戶ID、創(chuàng)建/過期時間、狀態(tài)等信息存儲在 MySQL。驗證時查詢數(shù)據(jù)庫,檢查 Token 是否存在、未過期且狀態(tài)有效。

數(shù)據(jù)庫表結(jié)構(gòu)

CREATE TABLE `user_token` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL COMMENT '用戶ID',
  `token` varchar(64) NOT NULL COMMENT '令牌值',
  `create_time` int(11) NOT NULL COMMENT '創(chuàng)建時間(時間戳)',
  `expire_time` int(11) NOT NULL COMMENT '過期時間(時間戳)',
  `status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '1-有效 0-無效',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_token` (`token`),
  KEY `idx_uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶令牌表';

實現(xiàn)代碼

<?php
$dbConfig = [
    'host' => '127.0.0.1',
    'user' => 'root',
    'password' => 'your_db_password',
    'dbname' => 'test',
    'charset' => 'utf8mb4'
];

function initDb() {
    global $dbConfig;
    try {
        $dsn = "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset={$dbConfig['charset']}";
        $pdo = new PDO($dsn, $dbConfig['user'], $dbConfig['password']);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $pdo;
    } catch (PDOException $e) {
        echo '數(shù)據(jù)庫連接失?。? . $e->getMessage();
        return null;
    }
}

function generateDbToken($uid, $expire = 3600) {
    $pdo = initDb();
    if (!$pdo) return false;
    $token = hash('sha256', $uid . time() . random_bytes(32));
    $createTime = time();
    $expireTime = $createTime + $expire;
    $sql = "INSERT INTO user_token (uid, token, create_time, expire_time, status) VALUES (:uid, :token, :create_time, :expire_time, 1)";
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':uid', $uid, PDO::PARAM_INT);
    $stmt->bindParam(':token', $token, PDO::PARAM_STR);
    $stmt->bindParam(':create_time', $createTime, PDO::PARAM_INT);
    $stmt->bindParam(':expire_time', $expireTime, PDO::PARAM_INT);
    return $stmt->execute() ? $token : false;
}

function verifyDbToken($token) {
    $pdo = initDb();
    if (!$pdo) return false;
    $now = time();
    $sql = "SELECT uid FROM user_token WHERE token = :token AND status = 1 AND expire_time > :now LIMIT 1";
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':token', $token, PDO::PARAM_STR);
    $stmt->bindParam(':now', $now, PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($result) {
        return (int)$result['uid'];
    }
    return false;
}

function destroyDbToken($token) {
    $pdo = initDb();
    if (!$pdo) return false;
    $sql = "UPDATE user_token SET status = 0 WHERE token = :token";
    $stmt = $pdo->prepare($sql);
    $stmt->bindParam(':token', $token, PDO::PARAM_STR);
    return $stmt->execute() && $stmt->rowCount() > 0;
}

// 示例
$token = generateDbToken(1001);
echo '數(shù)據(jù)庫Token:' . $token . '<br>';

$clientToken = $_SERVER['HTTP_TOKEN'] ?? '';
$uid = verifyDbToken($clientToken);
if ($uid) {
    echo 'Token驗證通過,用戶ID:' . $uid;
} else {
    echo 'Token無效或已過期';
}

// destroyDbToken($clientToken);
?>

優(yōu)缺點

優(yōu)點缺點
支持復(fù)雜 Token 管理(如批量禁用、查詢記錄)數(shù)據(jù)庫 IO 性能低于 Redis/Session,高并發(fā)下易成瓶頸
數(shù)據(jù)持久化,方便追溯需手動清理過期 Token,表數(shù)據(jù)易膨脹
可擴展字段,便于審計分布式部署需考慮主從同步
支持主動銷毀 Token代碼復(fù)雜度高,需處理事務(wù)、異常等

各方案對比匯總表

對比維度Session TokenJWT TokenRedis Token數(shù)據(jù)庫 Token
存儲位置服務(wù)端(文件/內(nèi)存)客戶端服務(wù)端(Redis)服務(wù)端(MySQL)
狀態(tài)特性有狀態(tài)無狀態(tài)有狀態(tài)有狀態(tài)
分布式支持需 Session 共享天然支持Redis 集群主從同步/分庫分表
主動銷毀支持不支持(需黑名單)支持支持
性能極高
復(fù)雜度
適用場景小型項目、CSRF 防護前后端分離、無狀態(tài)服務(wù)中大型項目、分布式審計、復(fù)雜權(quán)限、低并發(fā)
安全性

總結(jié)與選型建議

選型核心原則

  • 小型單節(jié)點項目:優(yōu)先選用 Session Token(實現(xiàn)簡單)。
  • 前后端分離/跨域場景:優(yōu)先選用 JWT Token(無狀態(tài),易于擴展)。
  • 中大型分布式項目:優(yōu)先選用 Redis Token(性能與靈活性兼具)。
  • 需審計/復(fù)雜管理場景:可選 數(shù)據(jù)庫 Token(持久化與擴展性強)。

安全性建議

  • 所有 Token 建議通過 HTTPS 傳輸,防止明文泄露。
  • JWT 密鑰需定期更換,且嚴密保管。
  • Session/Redis/數(shù)據(jù)庫 Token 建議設(shè)置合理有效期,驗證后一次性銷毀(CSRF 場景)或滑動刷新(登錄態(tài)場景)。

混合使用場景

  • 可結(jié)合 JWT + Redis,實現(xiàn)“無狀態(tài) + 可銷毀”機制:JWT 存儲基礎(chǔ)信息,Redis 存儲 JWT 黑名單,兼顧性能與靈活性。

以上就是PHP中四種主流Token實現(xiàn)方案的詳細內(nèi)容,更多關(guān)于PHP Token主流實現(xiàn)方案的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

特克斯县| 太谷县| 孝义市| 晋中市| 上栗县| 三亚市| 调兵山市| 互助| 曲松县| 信宜市| 油尖旺区| 五台县| 奉贤区| 新闻| 防城港市| 遂宁市| 古交市| 聂拉木县| 四平市| 莎车县| 晋江市| 怀来县| 越西县| 珠海市| 新民市| 万宁市| 湟源县| 浠水县| 丹棱县| 拉萨市| 黎城县| 仪陇县| 勐海县| 白银市| 建德市| 隆回县| 应城市| 武城县| 焦作市| 蕉岭县| 大洼县|