JWT

JWT是什么

JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。

JWT作用

根据用户基本信息、过期时间、秘钥生成时间等信息生成一个加密字符串(token)。
根据客户端提交过来的加密字符串token,进行解码,验证用户信息真实性、token是否在有效期内,成功之后,返回请求信息。

JWT流程

初次登录,验证登录信息。
验证通过,生成JWT。
返还JWT,存入客户端。
客户端请求接口,带JWT。
服务器验证JWT(用户信息,是否过期)。
如果过期,重新生成JWT。(也可以通过Redis来模拟过期时间)

关键字

jti // 唯一标识
iss // 签发者
aud // 听众
uid // 用户id
iat // 签发时间
exp // 过期时间
nbf // 该时间之前不接收处理该Token

三种操作

生成JWT,
解析JWT(验证用户信息),
验证JWT(验证是否过期,以及加密信息是否一致)。

composer

composer require lcobucci/jwt

操作案例

创建

use Lcobucci\JWT\Builder;
$token = (new Builder())->setIssuer('http://example.com') // 配置签发者
->setAudience('http://example.org') // 配置听众
->setId('aaabbbcccddd', true) // 配置唯一标示
->setIssuedAt(time()) // 签发时间
->setNotBefore(time() + 60) // 该时间之前不接收处理该Token
->setExpiration(time() + 3600) // 过期时间
->set('uid', 1) // 用户id,这个随意
->set('openid', 'hello,world') // openid,随意
->getToken(); // 生成token

//print_r($token->getHeaders()); // 检索头部
//print_r($token->getClaims()); // 检索请求,声明

echo $token->getHeader('jti').PHP_EOL; // 唯一标识
echo $token->getClaim('iss').PHP_EOL; // 签发者
echo $token->getClaim('aud').PHP_EOL; // 听众
echo $token->getClaim('uid').PHP_EOL; // 用户id
echo $token->getClaim('iat').PHP_EOL; // 签发时间
echo $token->getClaim('exp').PHP_EOL; // 过期时间
echo $token->getClaim('nbf').PHP_EOL; // 该时间之前不接收处理该Token
echo $token; // JWT字符串

解析

use Lcobucci\JWT\Parser;
$token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIiwianRpIjoiYWFhYmJiY2NjZGRkIn0.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiYWFhYmJiY2NjZGRkIiwiaWF0IjoxNTU3NTYwMzk4LCJuYmYiOjE1NTc1NjAzOTksImV4cCI6MTU1NzU2MDQ5OCwidWlkIjoxfQ.aaabbbcccddd';
$token = (new Parser())->parse((string) $token); // 解析成对象
//print_r($token->getHeaders()); // 检索头部
//print_r($token->getClaims()); // 检索请求,声明

echo $token->getHeader('jti').PHP_EOL; // 唯一标识
echo $token->getClaim('iss').PHP_EOL; // 签发者
echo $token->getClaim('aud').PHP_EOL; // 听众
echo $token->getClaim('uid').PHP_EOL; // 用户id
echo $token->getClaim('iat').PHP_EOL; // 签发时间
echo $token->getClaim('exp').PHP_EOL; // 过期时间
echo $token->getClaim('nbf').PHP_EOL; // 该时间之前不接收处理该Token

验证

use Lcobucci\JWT\ValidationData;
$data = new ValidationData(); // 默认使用当前时间进行验证 (iat, nbf and exp)
$data->setIssuer('http://example.com');
$data->setAudience('http://example.org');
$data->setId('aaabbbcccddd');

var_dump($token->validate($data)); // false, 当前时间不可用
$data->setCurrentTime(time() + 60); // 改变时间
var_dump($token->validate($data)); // true, 满足60秒及其以后
$data->setCurrentTime(time() + 4000); // 继续改变
var_dump($token->validate($data)); // false, 已经过期

封装成类

<?php
/**
 * 工具类,无关数据库
 * User: Eden
 * Date: 19-4-26 上午9:23
 */

namespace Common\Util;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\ValidationData;

class TokenUtil extends CommonUtil
{
    /**
     * 生成token
     * @param $uid
     * @param int $exp
     * @param int $nbf
     * @return \Lcobucci\JWT\Token
     */
    public static function createToken($uid,$exp = 86400,$nbf = 0) {
        $token = (new Builder())->setIssuer(C('TOKEN.ISS')) // 配置签发者
        ->setAudience(C('TOKEN.AUD')) // 配置听众
        ->setId(C('TOKEN.JTI'), true) // 配置唯一标示
        ->setIssuedAt(time()) // 签发时间
        ->setNotBefore(time() + $nbf) // 该时间之前不接收处理该Token,0表示立即生效
        ->setExpiration(time() + $exp) // 过期时间
        ->set('uid', $uid) // 用户id,这个随意
        ->getToken(); // 生成token
        return $token;
    }

    /**
     * 解析token
     * @param $token
     * @return array|bool
     */
    public static function parseToken($token) {
        if (!$token) {
            return false;
        }
        $token = (new Parser())->parse((string) $token); // 解析成对象
        return [
            'jti' => $token->getHeader('jti'), // 唯一标识
            'iss' => $token->getClaim('iss'), // 签发者
            'aud' => $token->getClaim('aud'), // 听众
            'uid' => $token->getClaim('uid'), // 用户id
            'iat' => $token->getClaim('iat'), // 签发时间
            'exp' => $token->getClaim('exp'), // 过期时间
            'nbf' => $token->getClaim('nbf'), // 该时间之前不接收处理该Token
        ];
    }

    /**
     * 验证有效,验证是否过期
     * @param $token
     * @param int $current_time
     * @return bool
     */
    public static function validateToken($token,$current_time = 0) {
        $token = (new Parser())->parse((string) $token); // 解析成对象
        $data = new ValidationData(); // 默认使用当前时间进行验证 (iat, nbf and exp)
        $data->setIssuer(C('TOKEN.ISS'));
        $data->setAudience(C('TOKEN.AUD'));
        $data->setId(C('TOKEN.JTI'));
        if ((int)$current_time !== 0) {
            $data->setCurrentTime($current_time); // 改变时间
        }
        return $token->validate($data);
    }
}
posted @ 2019-05-11 16:57  TBHacker  阅读(601)  评论(0编辑  收藏  举报