MENU

ThinkPHP6 使用 jwt-auth 组件

July 17, 2022 • Read: 1784 • PHP,编码

github地址:https://github.com/QThans/jwt-auth

安装 jwt 组件

composer require thans/tp-jwt-auth

生成密钥

php think jwt:create

自定义中间件

<?php
declare (strict_types = 1);
/**
 * 登录状态中间件,用来处理jwt的登录状态
 */
namespace app\middleware;

use thans\jwt\exception\JWTException;
use thans\jwt\exception\TokenBlacklistException;
use thans\jwt\exception\TokenBlacklistGracePeriodException;
use thans\jwt\exception\TokenExpiredException;
use thans\jwt\middleware\JWTAuth;
use think\exception\HttpException;

class Auth extends JWTAuth
{
    /**
     * 处理请求
     *
     * @param \think\Request $request
     * @param \Closure       $next
     * @return Response
     */
    public function handle($request, \Closure $next)
    {

        try {
            $payload = $this->auth->auth();
        } catch (TokenExpiredException $e) { // 捕获token过期
            // 尝试刷新token,会将旧token加入黑名单
            try {
                $this->auth->setRefresh();
                $token = $this->auth->refresh();
                $payload = $this->auth->auth(false);
            } catch (TokenBlacklistGracePeriodException $e) {
                $payload = $this->auth->auth(false);
            } catch (JWTException $exception) {
                // 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
                // throw new HttpException(401, $exception->getMessage());
                throw new HttpException(401, 'refresh 也过期了');
            }
        } catch (TokenBlacklistGracePeriodException $e) { // 捕获黑名单宽限期
            $payload = $this->auth->auth(false);
        } catch (TokenBlacklistException $e) { // 捕获黑名单,退出登录或者已经自动刷新,当前token就会被拉黑
            throw new HttpException(401, '当前用户未登录');
        } catch (JWTException $e){
            throw new HttpException(401, 'Token不能为空');
        }

        // 可以获取 payload里自定义的字段,比如uid
        $request->user_id = $payload['uid']->getValue();

        // 如果有新的token,则在响应头返回(前端判断一下响应中是否有 token,如果有就直接使用此 token 替换掉本地的 token,以此达到无痛刷新token效果)
        if (isset($token)) {
            $response = $next($request);
            $response = $response->header(['Access-Control-Expose-Headers' => 'Authorization,ExportFileName']);
            return $this->setAuthentication($response, $token);
        }
        return $next($request);
    }

}