PHP使用JWT實(shí)現(xiàn)API身份驗(yàn)證的完整流程
1. JWT簡(jiǎn)介
JWT由三部分組成:
Header-包含令牌的類型和使用的哈希算法(如HMAC SHA256或RSA)。
Payload-包含聲明(claims)。聲明是關(guān)于實(shí)體(通常是用戶)和其他數(shù)據(jù)的,有三種類型:注冊(cè)聲明、公共聲明和私有聲明。
Signature-對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。
例如,一個(gè)JWT看起來(lái)像這樣:`xxxxx.yyyyy.zzzzz`(三個(gè)Base64-URL字符串用點(diǎn)分隔)。
2. 環(huán)境準(zhǔn)備
在開始之前,確保你已經(jīng)安裝了PHP(建議7.4以上版本)和Composer。我們這里使用`firebase/php-jwt`庫(kù)來(lái)處理JWT的生成和驗(yàn)證。
composer require firebase/php-jwt
3. 用戶注冊(cè)與登錄
3.1 數(shù)據(jù)庫(kù)設(shè)計(jì)
為了簡(jiǎn)單起見,我們使用MySQL數(shù)據(jù)庫(kù)。創(chuàng)建一個(gè)名為users的表:
CREATE TABLE `users` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(50) NOT NULL UNIQUE, `password` VARCHAR(255) NOT NULL );
注意: 密碼必須是經(jīng)過哈希處理,用到的是PHP的password_hash()函數(shù)。
3.2 注冊(cè)接口
在注冊(cè)接口中,我們接收用戶名和密碼,將密碼哈希后存儲(chǔ)到數(shù)據(jù)庫(kù)。
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
// 連接數(shù)據(jù)庫(kù)
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'password');
function register($username, $password) {
global $pdo;
// 檢查用戶名是否已存在
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$username]);
if ($stmt->fetch()) {
return ['error' => 'User already exists'];
}
// 哈希密碼
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (?, ?)");
$stmt->execute([$username, $hash]);
return ['message' => 'User registered successfully'];
}
3.3 登錄接口
登錄時(shí),驗(yàn)證用戶名和密碼,如果正確,則生成JWT令牌返回給客戶端。
function login($username, $password) {
global $pdo;
$stmt = $pdo->prepare("SELECT id, password FROM users WHERE username = ?");
$stmt->execute([$username]);
$user = $stmt->fetch();
if (!$user || !password_verify($password, $user['password'])) {
return ['error' => 'Invalid credentials'];
}
// 生成JWT
$secret_key = "your_secret_key"; // 應(yīng)該是一個(gè)復(fù)雜的隨機(jī)字符串,存儲(chǔ)在環(huán)境變量中
$payload = [
'iss' => 'localhost', // 簽發(fā)者
'aud' => 'localhost', // 接收方
'iat' => time(), // 簽發(fā)時(shí)間
'exp' => time() + 3600, // 過期時(shí)間(1小時(shí))
'data' => [
'user_id' => $user['id'],
'username' => $username
]
];
$jwt = JWT::encode($payload, $secret_key, 'HS256');
return ['token' => $jwt];
}
4. 驗(yàn)證JWT
在需要身份驗(yàn)證的API(例如用戶個(gè)人信息接口)中,我們需要驗(yàn)證客戶端傳來(lái)的JWT。
function getProfile() {
// 獲取Authorization頭
$headers = getallheaders();
if (!isset($headers['Authorization'])) {
http_response_code(401);
return ['error' => 'Token not provided'];
}
$token = str_replace('Bearer ', '', $headers['Authorization']);
$secret_key = "your_secret_key";
try {
$decoded = JWT::decode($token, new Firebase\JWT\Key($secret_key, 'HS256'));
// 如果驗(yàn)證成功,$decoded將包含我們之前設(shè)置的payload
$user_id = $decoded->data->user_id;
// 現(xiàn)在可以根據(jù)user_id從數(shù)據(jù)庫(kù)獲取用戶信息并返回
// ... 數(shù)據(jù)庫(kù)查詢代碼 ...
return ['user' => $userInfo];
} catch (Exception $e) {
http_response_code(401);
return ['error' => 'Invalid token'];
}
}
5. 安全性考慮
- 使用HTTPS:在傳輸過程中保護(hù)JWT,防止被截獲。
- 密鑰安全:密鑰(
secret_key)必須足夠復(fù)雜,且不要硬編碼在代碼中,應(yīng)該使用環(huán)境變量。 - 令牌過期:設(shè)置合理的過期時(shí)間(如1小時(shí)),并考慮使用刷新令牌機(jī)制來(lái)延長(zhǎng)會(huì)話。
- 存儲(chǔ)方式:客戶端通常將JWT存儲(chǔ)在localStorage或sessionStorage中,但要注意XSS攻擊。也可以使用HttpOnly的Cookie來(lái)存儲(chǔ),避免XSS,但要注意CSRF防護(hù)。
6. 總結(jié)
通過本文,我們學(xué)習(xí)了如何在PHP中使用JWT進(jìn)行API身份驗(yàn)證。從用戶注冊(cè)登錄到JWT的生成與驗(yàn)證,我們實(shí)現(xiàn)了一套完整的流程。JWT提供了一種無(wú)狀態(tài)的認(rèn)證機(jī)制,非常適合分布式應(yīng)用和前后端分離架構(gòu)。當(dāng)然,安全是一個(gè)持續(xù)的過程,除了本文介紹的內(nèi)容,我們平時(shí)開發(fā)的時(shí)候還是需要關(guān)注其他安全措施,比如常見的輸入驗(yàn)證、基礎(chǔ)防止SQL注入等。
以上就是PHP使用JWT實(shí)現(xiàn)API身份驗(yàn)證的完整流程的詳細(xì)內(nèi)容,更多關(guān)于PHP JWT實(shí)現(xiàn)API身份驗(yàn)證的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
PHP基于timestamp和nonce實(shí)現(xiàn)的防止重放攻擊方案分析
這篇文章主要介紹了PHP基于timestamp和nonce實(shí)現(xiàn)的防止重放攻擊方案,簡(jiǎn)單講述了重放攻擊相關(guān)原理并結(jié)合實(shí)例形式分析了php使用timestamp和nonce實(shí)現(xiàn)的防止重放攻擊相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
PHP數(shù)組基本用法與知識(shí)點(diǎn)總結(jié)
這篇文章主要介紹了PHP數(shù)組基本用法與知識(shí)點(diǎn),總結(jié)整理了PHP數(shù)組基本概念、用法、定義、訪問、刪除等相關(guān)操作技巧,需要的朋友可以參考下2020-06-06
PHP面向?qū)ο蟪绦蛟O(shè)計(jì)組合模式與裝飾模式詳解
這篇文章主要介紹了PHP面向?qū)ο蟪绦蛟O(shè)計(jì)組合模式與裝飾模式,結(jié)合實(shí)例形式詳細(xì)分析了php組合模式與裝飾模式的定義、功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-12-12
PHP設(shè)置隨機(jī)數(shù)的方法小結(jié)
這篇文章主要介紹了PHP設(shè)置隨機(jī)數(shù)的方法,結(jié)合實(shí)例形式分析了php生成隨機(jī)數(shù)/生成隨機(jī)字符串的6種實(shí)現(xiàn)方法與相關(guān)操作注意事項(xiàng),文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-09-09
php 文件上傳后綴名與文件類型對(duì)照表(幾乎涵蓋所有文件)
在這個(gè)過程中會(huì)有一些瀏覽器兼容,更準(zhǔn)確來(lái)說(shuō)是文件類型解析標(biāo)識(shí)不一致的問題。2010-05-05

