Web 应用可分为客户端和服务端,这两者之间经常需要进行身份认证。
由于 HTTP 是无状态协议,不能保存认证后的用户状态,因此,每一次发送请求都需要重复的进行认证。
为了解决该问题,通常会使用 Cookie 来管理 Session,来实现用户状态管理。
服务器需要记录 Session 信息,当存在多台服务器时,这些服务器就需要共享 Session。例如,将 Session 数据进行持久化存储,每台服务器都从持久层中获取 Session。这种方案也有风险,当持久层突然失效时,所有登录信息都将失效。
由此可见,服务端保存认证状态是一件棘手的事,既然如此,何不将数据全都保存在客户端呢?Json Web Token 就是基于该思路提出的一种认证方案。
我们从 JSON Web Token 的命名就可以得出一些信息
JWT 的认证过程如下:
生成的 JWT 的格式如下
JWT 可分为三部分,用 . 符号隔开
{
"alg": "HS256",
"typ": "JWT"
}
Payload 携带令牌的具体内容,常用的内容如下
{
"sub": "1",
"name": "Mind Geek",
"admin": true
}
Signature 是加密 Header 和 Payload 后得到的签名,防止数据篡改,加密公式如下
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
mind-geek-jwt
)
解读
定义 Header
$header = [
‘alg‘ => ‘HS256‘,
‘typ‘ => ‘JWT‘,
];
定义 Payload
$payload = [
‘sub‘ => 1,
‘name‘ => ‘Mind Geek‘,
‘admin‘ => true,
];
定义密钥
$secret = ‘mind-geek-jwt‘;
将 Header 和 Payload 数组转化成 Json,再使用 Base64URL 算法进行编码。
function base64url(string $string)
{
return str_replace(‘=‘, ‘‘, strtr(base64_encode($string), ‘+/‘, ‘-_‘));
}
// Header
$base64Header = base64url(json_encode($header));
// Payload
$base64Payload = base64url(json_encode($payload));
将编码后的 Header 和 Payload 用 . 拼接起来
$encryp = $base64Header.".".$base64Payload;
对其进行加密,加密后再进行 Base64URL 编码,得到 Signature
$signature = hash_hmac(‘sha256‘, $encryp, $secret, true);
$base64Signature = base64url($signature);
拼接之后就是 JWT 字符串了
$token = $base64Header.".".$base64Payload.".".$base64Signature;
获取客户端发送的 JWT
$token = ‘eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEsIm5hbWUiOiJNaW5kIEdlZWsiLCJhZG1pbiI6dHJ1ZX0.0_dneYOin4yWRYlD-KmfvGEY6AhjA_zDyyvPhgYq2sU‘;
解析 JWT,得到编码过后的 Header、Payload 以及 Signature
list($base64Header, $base64Payload, $base64Signature) = explode(‘.‘, $token);
利用得到的 Header 和 Payload ,以及服务端保存的密钥来计算出签名
$encryp = $base64Header.".".$base64Payload;
$signature = hash_hmac(‘sha256‘, $encryp, $secret, true);
$computedBase64Signature = base64url($signature);
将计算出来的签名与客户端发送的签名进行对比
if($computedBase64Signature === $base64Signature){
echo "认证成功!";
}
原文:https://www.cnblogs.com/caibaotimes/p/13983034.html