lcobucci/jwt超级好用的封装教程

参数说明

iss 【issuer】签发人(可以是,发布者的url地址)

sub 【subject】该JWT所面向的用户,用于处理特定应用,不是常用的字段

aud 【audience】受众人(可以是客户端的url地址,用作验证是否是指定的人或者url)

exp 【expiration】 该jwt销毁的时间;unix时间戳

nbf 【not before】 该jwt的使用时间不能早于该时间;unix时间戳

iat 【issued at】 该jwt的发布时间;unix 时间戳

jti 【JWT ID】 该jwt的唯一ID编号

下载

composer require lcobucci/jwt 3.*

3.3

<?php

namespace tools\jwt;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;

/**
 * Created by PhpStorm.
 * User: asus
 * Date: 2019/4/5
 * Time: 13:02
 */
class Token
{
    private static $_config = [
        'audience' => 'http://www.pyg.com',//接收人
        'id' => '3f2g57a92aa',//token的唯一标识,这里只是一个简单示例
        'sign' => 'pinyougou',//签名密钥
        'issuer' => 'http://adminapi.pyg.com',//签发人
        'expire' => 3600 * 24 //有效期
    ];

    //生成token
    public static function getToken($user_id)
    {

        //签名对象
        $signer = new Sha256();
        //获取当前时间戳
        $time = time();
        //设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、签名
        $token = (new Builder())->issuedBy(self::$_config['issuer'])
            ->canOnlyBeUsedBy(self::$_config['audience'])
            ->identifiedBy(self::$_config['id'], true)
            ->issuedAt($time)
            ->canOnlyBeUsedAfter($time - 1)
            ->expiresAt($time + self::$_config['expire'])
            ->with('user_id', $user_id)
            ->sign($signer, self::$_config['sign'])
            ->getToken();
        return (string)$token;
    }

    //从请求信息中获取token令牌
    private static function getRequestToken()
    {
        if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
            return false;
        }

        $header = $_SERVER['HTTP_AUTHORIZATION'];
        $method = 'bearer';
        //去除token中可能存在的bearer标识
        return trim(str_ireplace($method, '', $header));
    }

    //从token中获取用户id (包含token的校验)
    public static function getUserId($token = null)
    {
        $user_id = null;

        $token = empty($token) ? self::getRequestToken() : $token;

        if (!empty($token)) {
            //为了注销token 加以下if判断代码
            $delete_token = cache('delete_token') ?: [];
            if (in_array($token, $delete_token)) {
                //token已被删除(注销)
                return $user_id;
            }
            $token = (new Parser())->parse((string)$token);
            //验证token
            $data = new ValidationData();
            $data->setIssuer(self::$_config['issuer']);//验证的签发人
            $data->setAudience(self::$_config['audience']);//验证的接收人
            $data->setId(self::$_config['id']);//验证token标识

            if (!$token->validate($data)) {
                //token验证失败
                return $user_id;
            }

            //验证签名
            $signer = new Sha256();
            if (!$token->verify($signer, self::$_config['sign'])) {
                //签名验证失败
                return $user_id;
            }
            //从token中获取用户id
            $user_id = $token->getClaim('user_id');


        }

        return $user_id;
    }
}

3.4 所有异常放一起验证

 //-------------------

            //验证接收人
            $audience = new PermittedFor(self::$_config['audience']);

            //验证是否过期
            $timezone = new DateTimeZone('Asia/Shanghai');
            $now = new SystemClock($timezone);
            $valid_at = new ValidAt($now);

            //把验证结果都放进去
            $config->setValidationConstraints($issued, $audience, $valid_at);
            //错误捕获
            try {
                $config->validator()->assert($token, ...$config->validationConstraints());
            } catch (RequiredConstraintsViolated $e) {


                if($e instanceof ValidAt){
                    echo "过期?";
                }



                dump($e->violations()[0]);

                die();
                //echo "捕获到异常了";
                //echo "这里是捕获到的错误";
                // list of constraints violation exceptions:

                //dump($e->violations());
                //
                //$res = $e->violations();
                //
                //var_dump($res[0]->getFile());


                //dump($e);
                //dump($e->violations());
            }

3.4 异常单独捕获然后通过json格式返回

<?php

namespace tools\jwt;

use DateTimeImmutable;
use DateTimeZone;
use InvalidArgumentException;
use Lcobucci\Clock\SystemClock;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;



use Lcobucci\JWT\Validation\Constraint\IssuedBy;
use Lcobucci\JWT\Validation\Constraint\PermittedFor;
use Lcobucci\JWT\Validation\Constraint\ValidAt;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;

class Token
{

    //配置属性
    private static $_config = [
        'issuer' => 'http://adminapi.pyg.com',//签发人
        'audience' => 'http://www.pyg.com',//接收人
        'id' => '3f2g57a92aa',//token的唯一标识,这里只是一个简单示例
        'sign' => 'pinyougou',//签名密钥
        'expire' => 3600 * 24 //有效期  86400
    ];


    //生成配置对象
    private static function getConfig()
    {
        return Configuration::forSymmetricSigner(
            new Sha256(),
            InMemory::plainText(self::$_config['id'])
        );
    }


    //生成token
    public static function getToken($user_id)
    {
        $config = self::getConfig();
        $now = new DateTimeImmutable();
        return $config->builder()
            ->issuedBy(self::$_config['issuer'])
            //接收人  // canOnlyBeUsedBy方法在4.x中将会被移除被permittedFor替代
            ->permittedFor(self::$_config['audience'])
            //唯一标志
            ->identifiedBy(self::$_config['id'])
            //签发时间
            ->issuedAt($now)
            //生效时间(立即生效:签发时间前一秒)
            ->canOnlyBeUsedAfter($now->modify('-1 second'))
            //过期时间
            ->expiresAt($now->modify('+20 second'))
            //用户id   // with方法在4.x中将会被移除被withClaim替代
            ->withClaim('user_id', $user_id)
            //签名
            ->getToken($config->signer(), $config->signingKey())->toString();
    }


    //从请求信息中获取token令牌
    public static function getRequestToken()
    {
        //取不到那就是没传递,返回false
        if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
            return false;
        }
        $header = $_SERVER['HTTP_AUTHORIZATION'];
        $method = 'bearer';

        //去除token中可能存在的bearer标识,这是一种兼容做法,因为前端传递的规范是可以有那个bearer的
        return trim(str_ireplace($method, '', $header));
    }


    //从token中获取用户id (包含token的校验)
    public static function getUserId($token = null)
    {
        $config = self::getConfig();

        $token = empty($token) ? self::getRequestToken() : $token;

        if (!empty($token)) {
            //注销token逻辑
            $delete_token = cache('delete_token') ?: [];
            if (in_array($token, $delete_token)) {
                //token已被删除(注销)
                return null;
            }
            //token解析异常必须要用try catch抓取
            try {
                //解析token
                $token = $config->parser()->parse((string)$token);
            } catch (\Exception $e) {
                // list of constraints violation exceptions:
                fail('token解析错误');
            }

            //验证签发人
            $issued = new IssuedBy(self::$_config['issuer']);
            if(!$config->validator()->validate($token,$issued)){
                fail('签发异常');
            }

            //验证接收
            $audience = new PermittedFor(self::$_config['audience']);
            if(!$config->validator()->validate($token,$audience)){
                fail('接收异常');
            }

            //验证是否过期
            $timezone = new DateTimeZone('Asia/Shanghai');
            $now = new SystemClock($timezone);
            $valid_at = new ValidAt($now);
            if(!$config->validator()->validate($token,$valid_at)){
                fail('token过期');
            }

            //从token中取出user_id
            return  $token->claims()->get('user_id');

        }
        return null;
    }


}

网上网友的版本(用于参考)

<?php
/**
 * jwt封装的一个简单的类
 */
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use DateTimeImmutable;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
use Lcobucci\JWT\Validation\Constraint\SignedWith;

class Service
{
    /**
     * 配置秘钥加密
     * @return Configuration
     */
    public static function getConfig()
    {
        $configuration = Configuration::forSymmetricSigner(
        // You may use any HMAC variations (256, 384, and 512)
            new Sha256(),
            // replace the value below with a key of your own!
            InMemory::base64Encoded('YWFhc0pOU0RLSkJITktKU0RiamhrMTJiM2Joa2ox')
        // You may also override the JOSE encoder/decoder if needed by providing extra arguments here
        );
        return $configuration;
    }

    /**
     * 签发令牌
     */
    public static function createToken()
    {
        $config = self::getConfig();
        assert($config instanceof Configuration);

        $now = new DateTimeImmutable();

        $token = $config->builder()
            // 签发人
            ->issuedBy('http://example.com')
            // 受众
            ->permittedFor('http://example.org')
            // JWT ID 编号 唯一标识
            ->identifiedBy('123')
            // 签发时间
            ->issuedAt($now)
            // 在1分钟后才可使用
//            ->canOnlyBeUsedAfter($now->modify('+1 minute'))
            // 过期时间1小时
            ->expiresAt($now->modify('+1 hour'))
            // 自定义uid 额外参数
            ->withClaim('uid', 1)
            // 自定义header 参数
            ->withHeader('foo', 'bar')
            // 生成token
            ->getToken($config->signer(), $config->signingKey());

        //result:
        //eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImZvbyI6ImJhciJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWEiLCJpYXQiOjE2MDk0Mjk3MjMsIm5iZiI6MTYwOTQyOTc4MywiZXhwIjoxNjA5NDMzMzIzLCJ1aWQiOjF9.o4uLWzZjk-GJgrxgirypHhXKkMMUEeL7z7rmvmW9Mnw
        //base64 decode:
        //{"typ":"JWT","alg":"HS256","foo":"bar"}{"iss":"http:\/\/example.com","aud":"http:\/\/example.org","jti":"4f1g23a12aa","iat":1609429723,"nbf":1609429783,"exp":1609433323,"uid":1}[6cb`"*Gr0ńxoL

        return $token->toString();
    }

    /**
     * 解析令牌
     */
    public static function parseToken(string $token)
    {
        $config = self::getConfig();
        assert($config instanceof Configuration);

        $token = $config->parser()->parse('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImZvbyI6ImJhciJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWEiLCJpYXQiOjE2MDk0Mjk3MjMsIm5iZiI6MTYwOTQyOTc4MywiZXhwIjoxNjA5NDMzMzIzLCJ1aWQiOjF9.o4uLWzZjk-GJgrxgirypHhXKkMMUEeL7z7rmvmW9Mnw'
        );

        assert($token instanceof Plain);

        dump($token->headers()); // Retrieves the token headers
        dump($token->claims()); // Retrieves the token claims
    }

    /**
     * 验证令牌
     */
    public static function validationToken(string $token)
    {
        $config = self::getConfig();
        assert($config instanceof Configuration);

        $token = $config->parser()->parse($token);
        assert($token instanceof Plain);

//Lcobucci\JWT\Validation\Constraint\IdentifiedBy: 验证jwt id是否匹配
//Lcobucci\JWT\Validation\Constraint\IssuedBy: 验证签发人参数是否匹配
//Lcobucci\JWT\Validation\Constraint\PermittedFor: 验证受众人参数是否匹配
//Lcobucci\JWT\Validation\Constraint\RelatedTo: 验证自定义cliam参数是否匹配
//Lcobucci\JWT\Validation\Constraint\SignedWith: 验证令牌是否已使用预期的签名者和密钥签名
//Lcobucci\JWT\Validation\Constraint\ValidAt: 验证要求iat,nbf和exp(支持余地配置)

        //验证jwt id是否匹配
        $validate_jwt_id = new \Lcobucci\JWT\Validation\Constraint\IdentifiedBy('123');
        $config->setValidationConstraints($validate_jwt_id);
        //验证签发人url是否正确
        $validate_issued = new \Lcobucci\JWT\Validation\Constraint\IssuedBy('http://example.com');
        $config->setValidationConstraints($validate_issued);
        //验证客户端url是否匹配
        $validate_aud = new \Lcobucci\JWT\Validation\Constraint\PermittedFor('http://example.org');
        $config->setValidationConstraints($validate_aud);

        //验证是否过期
        $timezone = new \DateTimeZone('Asia/Shanghai');
        $now = new \Lcobucci\Clock\SystemClock($timezone);
        $validate_jwt_at = new \Lcobucci\JWT\Validation\Constraint\ValidAt($now);
        $config->setValidationConstraints($validate_jwt_at);

        $constraints = $config->validationConstraints();

        try {
            $config->validator()->assert($token, ...$constraints);
        } catch (RequiredConstraintsViolated $e) {
            // list of constraints violation exceptions:
            var_dump($e->violations());
        }
    }

}
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值