Thinkphp5.1 使用jwt生成和解析token 一 2021-04-01

一 通过Composer安装firebase/php-jwt 5.2.1版本

composer require firebase/php-jwt  版本号

二 common.php公共函数文件

use Firebase\JWT\JWT;      //引入JWT



/**
 * @param $data
 * @return string
 * 生成token
 */
function setToken($data)
{
    $key = 'key';   //秘钥:自定义
    $payload = array(
        'iss' => '',                    //签发人(官方字段:非必需)
        'aud' => '',                    //受众(官方字段:非必需)
        'iat' => time(),                //签发时间
        'nbf' => time(),                //生效时间
        'exp' => time() + 3600,         //过期时间
        'uid' => $data                 //自定义字段
    );
    //加密生成token
    $jwt = JWT::encode($payload, $key);
    return $jwt;
}


/**
 * @param $token
 * @return mixed
 * 解析token
 */
function chekToken()
{
    try {
        $key = 'key';
        JWT::$leeway = 60;//当前时间减去60,把时间留点余地
        $decoded = JWT::decode($header['token'], $key, array('HS256')); //HS256方式,这里要和签发的时候对应
        $this->uid = $decoded->uid;
    } catch (\Firebase\JWT\SignatureInvalidException $e) {  //签名不正确
        echo $e->getMessage();
        exit();
    } catch (\Firebase\JWT\BeforeValidException $e) {  // 签名在某个时间点之后才能用
        echo $e->getMessage();
        exit();
    } catch (\Firebase\JWT\ExpiredException $e) {  // token过期
        echo $e->getMessage();
        exit();
    } catch (\Exception $e) {  //其他错误
        echo $e->getMessage();
        exit();
    }
}
  • 封装单例模式
<?php
/**
 * Created by PhpStorm.
 * User: EDZ
 * Date: 2019/8/28
 * Time: 12:41
 */

namespace app\common\Auth;

use Firebase\JWT\JWT;

class JwtAuth
{
    // 秘钥
    private $key = 'defined-202002022020-xxxxx-key';
    // 发行人
    private $iss = 'www.test.com';
    // 受众
    private $aud = 'www';
    // 登录id
    private $uid;
    // 权限
    private $role;
    // 加密token
    private $token;
    // 解密token
    private $decodeToken;

    // 单例
    private static $instance;

    /**
     * 单例模式
     * @return JwtAuth
     */
    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 私有化构造函数
     * JwtAuth constructor.
     */
    private function __construct()
    {
    }

    /**
     * 私有化克隆函数
     */
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    // 获取uid
    public function getUid()
    {
        return $this->uid;
    }

    // 设置uid
    public function setUid($uid)
    {
        $this->uid = $uid;
        return $this;
    }

    // 获取role
    public function getRole()
    {
        return $this->role;
    }

    // 设置role
    public function setRole($role)
    {
        $this->role = $role;
        return $this;
    }

    // 设置token
    public function setToken($token)
    {
        $this->token = $token;
        return $this;
    }

    // 获取token
    public function getToken()
    {
        return (string)$this->token;
    }

    /**
     * 加密token
     * @return $this
     */
    public function encode()
    {
        $time = time();
        $params = [
            'iss' => $this->iss,
            'aud' => $this->aud,
            'iat' => $time, // 签发时间
            'nbf' => $time + 10, // 该时间段不允许操作token
            'exp' => $time + 3600 * 24 * 7, // 过期时间7天
            'uid' => $this->uid,//uid
            'role' => $this->role,//role
        ];
        $this->token = JWT::encode($params, $this->key, "HS256");
        return $this;
    }

    /**
     * 解密token
     * @param $jwt
     * @return array
     */
    public function decode($jwt)
    {
        JWT::$leeway = 60;
        $decoded = JWT::decode($jwt, $this->key, ["HS256"]);
        $this->decodeToken = (array)$decoded;
        $this->uid = $this->decodeToken['uid'];
        $this->role = $this->decodeToken['role'];
        return $this->decodeToken;
    }
}
  • 登录调用
        $jwt = JwtAuth::getInstance();
        $token = $jwt->setUid($uid)->setRole($role)->encode()->getToken();//获取token
  • 路由中间件拦截验证token
    public function handle($request, \Closure $next)
    {
        $token = $request->param('token');
        if ($token) {
            $jwt = JwtAuth::getInstance();
            $decodeToken = $jwt->decode($token);
            if (!$decodeToken) {
                throw new BaseExecption(ApiErrorDesc::ERR_TOKEN);
            }
            if ($decodeToken['exp'] < time()) {
                throw new BaseExecption(ApiErrorDesc::ERR_LOGIN_EXPIRE);
            }
            return $next($request);
        } else {
            throw new BaseExecption(ApiErrorDesc::ERR_PARAMS);
        }
    }
  • Base公共控制器获取用户信息以及权限避免重复查询数据库
<?php
/**
 * Created by PhpStorm.
 * User: EDZ
 * Date: 2019/9/2
 * Time: 11:33
 */

namespace app\index\controller;

use app\index\common\Auth\JwtAuth;
use think\Controller;

header("Access-Control-Allow-Credentials:true");
header('Access-Control-Allow-Origin:*');

class Base extends Controller
{
    protected $uid;
    protected $role;

    public function __construct()
    {
        $token = input('token');
        $jwt = JwtAuth::getInstance();
        $this->uid = $jwt->setToken($token)->getUid();
        $this->role = $jwt->setToken($token)->getRole();


        parent::__construct();
    }
}
  • 单例模式
class JwtAuth
{
    // 秘钥
    const KEY = 'defined-202002022020-testkeyauto-key';
    // 发行人
    const ISS = 'quality.test.com';
    // 受众
    const AUD = 'quality';

    // 登录id
    private $uid;
    // 权限
    private $role;
    // 加密token
    private $token;
    // 解密token
    private $decodedToken;

    // 单例
    private static $instance;

    /**
     * 私有化构造函数
     */
    private function __construct()
    {
        $this->uid = null;
        $this->role = null;
    }

    /**
     * 单例模式
     * @return JwtAuth
     */
    public static function getInstance()
    {
        if (!isset(self::$instance) || is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * 私有化克隆函数
     */
    private function __clone()
    {
        // TODO: Implement __clone() method.
    }

    /**
     * 设置登录 id 和权限
     * @param $uid
     * @param $role
     * @return $this
     */
    public function setAuth($uid, $role)
    {
        $this->uid = $uid;
        $this->role = $role;
        return $this;
    }

    /**
     * 加密token
     * @param array $payload JWT 配置项
     * @return $this
     */
    public function encode(array $payload = [])
    {
        $params = array_merge([
            'iss' => self::ISS,
            'aud' => self::AUD,
            'nbf' => time() + 10, // 该时间段不允许操作token
            'exp' => time() + 3600 * 24 * 7, // 过期时间
            'uid' => $this->uid,
            'role' => $this->role
        ], $payload);
        $this->token = JWT::encode($params, self::KEY, "HS256");
        return $this;
    }

    /**
     * 解密token
     * @param string $jwt 待解密的 token
     * @return array
     */
    public function decode(string $jwt)
    {
        try {
            $decoded = JWT::decode($jwt, self::KEY, array("HS256"));
            $this->decodedToken = (array)$decoded;
            return $this->decodedToken;
        } catch (Firebase\JWT\ExpiredException | Firebase\JWT\SignatureInvalidException $e) {
            // Log or handle the error as appropriate
            return false;
        }
    }

    /**
     * 获取解密后的 uid
     * @return int|null
     */
    public function getUid()
    {
        if (isset($this->decodedToken['uid'])) {
            return $this->decodedToken['uid'];
        } else {
            return null;
        }
    }

    /**
     * 获取解密后的权限
     * @return string|null
     */
    public function getRole()
    {
        if (isset($this->decodedToken['role'])) {
            return $this->decodedToken['role'];
        } else {
            return null;
        }
    }

    /**
     * 获取加密后的 token
     * @return string|null
     */
    public function getToken()
    {
        return $this->token;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容