商务合作加微信:2230304070
学习与交流:PHP技术交流微信群
在现代 Web 应用中,用户认证是一个非常重要的环节。传统的 Session 认证方式存在一些问题,例如难以扩展、无法跨域等。而 JWT(JSON Web Token)作为一种无状态的认证机制,逐渐成为主流。
JWT 的优点是轻量、自包含、易于跨域使用,但它也存在一个缺点:Token 的有效期是固定的,过期后用户需要重新登录,这会影响用户体验。
为了解决这个问题,我们可以使用双令牌(Access Token 和 Refresh Token)机制,并结合无感续约技术,实现用户无感知的 Token 自动续约。
本文将详细介绍 JWT 的原理、数据结构、认证流程,以及如何通过双令牌机制实现无感续约,并提供 PHP 代码实例。
JWT 原理
JWT 是一种基于 JSON 的开放标准(RFC 7519),用于在网络应用环境间安全地传递声明(Claims)。JWT 由三部分组成:
JWT 的格式如下:
Header.Payload.SignatureHeader 通常包含两部分:
alg:签名算法,例如 HMAC SHA256 或 RSA。typ:Token 类型,通常是 JWT。示例:
{"alg":"HS256","typ":"JWT"}Payload 包含声明(Claims),声明分为三类:
exp(过期时间)、sub(主题)等。示例:
{"sub":"1234567890","name":"John Doe","iat":1516239022,"exp":1516242622}Signature 是对 Header 和 Payload 的签名,用于验证 Token 是否被篡改。签名算法的公式如下:
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload), secret)当 Access Token 过期时,客户端使用 Refresh Token 请求新的 Access Token。如果 Refresh Token 仍然有效,服务器会返回新的 Access Token,客户端无需重新登录。
useFirebase\JWT\JWT;functiongenerateJWT($payload,$secret,$expiry){$payload['iat']=time();// 签发时间$payload['exp']=time()+$expiry;// 过期时间returnJWT::encode($payload,$secret,'HS256');}// 生成 Access Token$accessToken=generateJWT(['sub'=>'123'],'your_secret_key',900);// 15 分钟// 生成 Refresh Token$refreshToken=generateJWT(['sub'=>'123'],'your_refresh_secret_key',604800);// 7 天useFirebase\JWT\JWT;useFirebase\JWT\Key;functionvalidateJWT($token,$secret){try{$decoded=JWT::decode($token,newKey($secret,'HS256'));return(array)$decoded;}catch(\Exception$e){returnnull;// Token 无效}}// 验证 Access Token$accessToken='your_access_token';$decoded=validateJWT($accessToken,'your_secret_key');if($decoded){echo"Token 有效: ".print_r($decoded,true);}else{echo"Token 无效";}functionrefreshAccessToken($refreshToken){$decoded=validateJWT($refreshToken,'your_refresh_secret_key');if($decoded){// 生成新的 Access Token$newAccessToken=generateJWT(['sub'=>$decoded['sub']],'your_secret_key',900);return$newAccessToken;}returnnull;// Refresh Token 无效}// 客户端请求续约$refreshToken='your_refresh_token';$newAccessToken=refreshAccessToken($refreshToken);if($newAccessToken){echo"新的 Access Token: ".$newAccessToken;}else{echo"Refresh Token 无效,请重新登录";}// 假设 Access Token 存储在 localStorage 中let accessToken =localStorage.getItem('accessToken');asyncfunctionfetchWithToken(url, options ={}){ options.headers= options.headers||{}; options.headers['Authorization']=`Bearer ${accessToken}`;let response =awaitfetch(url, options);if(response.status===401){// Token 过期let newToken =awaitrefreshToken();if(newToken){ accessToken = newToken;localStorage.setItem('accessToken', newToken); options.headers['Authorization']=`Bearer ${newToken}`; response =awaitfetch(url, options);// 重试请求}else{// 跳转到登录页window.location.href='/login';}}return response;}asyncfunctionrefreshToken(){let response =awaitfetch('/refresh-token',{method:'POST',credentials:'include'// 发送 Refresh Token(存储在 Cookie 中)});if(response.ok){let data =await response.json();return data.accessToken;}returnnull;}通过 JWT 双令牌机制,我们可以实现用户无感知的 Token 自动续约,提升用户体验。Access Token 用于短期访问,Refresh Token 用于长期续约,两者结合既保证了安全性,又避免了频繁登录的麻烦。
在实际开发中,需要注意以下几点:


丨热门教程资源免费领丨



上下滑动查看更多
(在下方公众号回复「资料」,即可领取哦)
↓↓↓
点个赞

再走吧