首先了解一下什么是JWT
JWT 是一种开放标准(RFC 7519),用于在各方之间以 JSON 对象形式安全传输信息4。其核心特点包括:
结构:由三部分组成(Header、Payload、Signature),通过点号分隔,例如 xxxxx.yyyyy.zzzzz2。
Header:声明加密算法和 Token 类型(如 HS256)。
Payload:包含用户信息、注册声明(如 iss、exp)和自定义数据。
Signature:通过密钥对前两部分签名,确保数据完整性。
用途:
身份认证:用户登录后,服务端生成 JWT 返回客户端,客户端后续请求携带 JWT 以访问受保护资源1。
JWT的优势
-
无状态性
优势:JWT 自身包含用户身份和权限信息,服务端无需存储会话数据(如 Session),直接通过验证 Token 签名即可完成认证。 效果:降低服务端资源消耗,天然支持分布式系统和横向扩展。 对比:传统 Session 需要服务端维护会话状态,多服务器场景需共享 Session 存储(如 Redis),增加复杂度。
-
跨域支持
优势:JWT 通过 HTTP 头(如 Authorization: Bearer <token>)传递,不受 Cookie 同源策略限制。 应用场景:适合前后端分离、跨域 API 调用及微服务架构。 对比:Cookie 需额外配置 CORS 策略,且存在跨域限制。
-
安全性增强
优势:防 CSRF:Token 存储在客户端而非 Cookie,避免跨站请求伪造攻击。 防篡改:签名机制(如 HS256)确保 Token 内容完整性和来源可信。
-
标准化与灵活性
优势:JWT 遵循 RFC 7519 标准,支持多种签名算法(如 RSA、HMAC)和自定义声明(Claims),便于集成第三方服务。 扩展场景:单点登录(SSO)、API 网关鉴权等。
搭建JWT工具类
首先确定一些参数
php
private static $key = '4875c029de194dd79ade2ee5aa68ee57';//密钥
private const exp = 3600;//token过期时间 1小时
private const alg = 'HS256';//加密算法
private const iss = 'ceshi';// 签发人
private const aud = 'web';// 受众
密钥可以自己随便写,但是建议不要太简单
签发人一般是用于校验该token是不是自己的
受众一般是用于区分web和app端的
密钥可以使用下面代码生成一个
php
public function init()
{
$md5 = md5(time());
return $md5;
}
生成密钥的方法
php
public static function createToken($data)
{
$time = time();
$payload = [
"iat" => $time, // 签发时间
"nbf" => $time, // 生效时间
"exp" => self::exp + $time, // 失效时间
"iss" => self::iss,// 签发人
"aud" => self::aud,// 受众
"data" => $data, // 自定义数据
];
return JWT::encode($payload, self::$key, self::alg);
}
使用样例
php
$token = Token::createToken(['id' => '1', 'role' => 'admin']);
解析密钥并校验的方法
解析方法
php
private static function decodeToken($token)
{
try {
return JWT::decode($token, new Key(self::$key, self::alg));
} catch (\Exception $e) {
throw new HttpResponseException(json(['code' => 401, 'msg' => 'token无效']));
}
}
验证管理员
php
public static function isAdmin($token)
{
$decodeToken = self::decodeToken($token);
return $decodeToken->data->role === 'admin';
}
使用样例
php
if (!Token::isAdmin($token)) {
$this->error('权限不足');
}
验证是否为本人token
php
public static function checkSelf($userId, $token)
{
$decodeToken = self::decodeToken($token);
return $decodeToken->data->id == $userId;
}
使用样例
php
if (!Token::checkSelf($id, $token)) {
$this->error('权限不足');
}
完整代码
php
<?php
namespace app\common\library;//这个命名空间记得要换成自己的
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\exception\HttpResponseException;
class Token
{
private static $key = '4875c029de194dd79ade2ee5aa68ee57';//密钥
private const exp = 3600;//token过期时间 1小时
private const alg = 'HS256';//加密算法
private const iss = 'ceshi';// 签发人
private const aud = 'web';// 受众
public static function createToken($data)
{
$time = time();
$payload = [
"iat" => $time, // 签发时间
"nbf" => $time, // 生效时间
"exp" => self::exp + $time, // 失效时间
"iss" => self::iss,// 签发人
"aud" => self::aud,// 受众
"data" => $data, // 自定义数据
];
return JWT::encode($payload, self::$key, self::alg);
}
public static function isAdmin($token)
{
$decodeToken = self::decodeToken($token);
return $decodeToken->data->role === 'admin';
}
public static function checkSelf($userId, $token)
{
$decodeToken = self::decodeToken($token);
return $decodeToken->data->id == $userId;
}
private static function decodeToken($token)
{
try {
return JWT::decode($token, new Key(self::$key, self::alg));
} catch (\Exception $e) {
throw new HttpResponseException(json(['code' => 401, 'msg' => 'token无效']));
}
}
}
使用JWT需要额外安装扩展
php
composer require firebase/php-jwt