您现在的位置是:群英 > 开发技术 > 编程语言
详解PHP实现JWT登录鉴权的过程是什么
Admin发表于 2022-09-20 17:56:30904 次浏览
这篇文章给大家分享的是“详解PHP实现JWT登录鉴权的过程是什么”,文中的讲解内容简单清晰,对大家学习和理解有一定的参考价值和帮助,有这方面学习需要的朋友,接下来就跟随小编一起学习一下“详解PHP实现JWT登录鉴权的过程是什么”吧。



一、什么是JWT

1、简介

JWT(JSON Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。

简单的说,JWT就是一种Token的编码算法,服务器端负责根据一个密码和算法生成Token,然后发给客户端,客户端只负责后面每次请求都在HTTP header里面带上这个Token,服务器负责验证这个Token是不是合法的,有没有过期等,并可以解析出subject和claim里面的数据。

2、JWT的组成

第一部分为头部(header),第二部分我们称其为载荷(payload),第三部分是签证(signature)。【中间用 . 分隔】

一个标准的JWT生成的token格式如下:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjRmMWcyM2ExMmFhMTEifQ.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWExMSIsImlhdCI6MTY0MDE3MTA1MywibmJmIjoxNjQwMTcxMDU0LCJleHAiOjE2NDAxNzQ2NTMsInVpZCI6MjAsInVzZXJuYW1lIjoiTWFrZSJ9.bysUwNIyhqqEyL0JecSHdplSTfE6G6zuCsrAn6eyrQM

使用https://jwt.io/这个网站对JWT Token进行解析的结果如下

3、JWT验证流程和特点

验证流程:

① 在头部信息中声明加密算法和常量, 然后把header使用json转化为字符串

② 在载荷中声明用户信息,同时还有一些其他的内容;再次使用json 把载荷部分进行转化,转化为字符串

③ 使用在header中声明的加密算法和每个项目随机生成的secret来进行加密, 把第一步分字符串和第二部分的字符串进行加密, 生成新的字符串。词字符串是独一无二的。

④ 解密的时候,只要客户端带着JWT来发起请求,服务端就直接使用secret进行解密。

特点:

① 三部分组成,每一部分都进行字符串的转化

② 解密的时候没有使用数据库,仅仅使用的是secret进行解密

③ JWT的secret千万不能泄密!

④ 不依赖数据库,而是直接根据token取出保存的用户信息,以及对token可用性校验,校验方式更加简单便捷化,单点登录更为简单。

二、相关问题

  • JWT Token需要持久化在redis、Memcached中吗?

不应该这样做,无状态的jwt变成了有状态了,背离了JWT通过算法验证的初心。

  • 在退出登录时怎样实现JWT Token失效呢?

退出登录, 只要客户端端把Token丢弃就可以了,服务器端不需要废弃Token。

  • 怎样保持客户端长时间保持登录状态?

服务器端提供刷新Token的接口, 客户端负责按一定的逻辑刷新服务器Token。

三、PHP实现

1、引入依赖

composer require lcobucci/jwt 3.*

2、功能实现

  • 签发token, 设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、用户username、签名。其中,用户id、用户username是特意存储在token中的信息,也可以增加一些其他信息,这样在解析的时候就可以直接获取到这些信息,不能是敏感数据
  • 验证令牌验证这个Token是不是合法的,有没有过期等,并可以解析出subject和claim里面的数据,传递jwt token的方式为Authorization中的Bearer Token,如下

3、封装工具类如下

<?php
/**
 * Created by PhpStorm
 * @author sxd
 */

namespace App\Utils;


use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\Constraint\IdentifiedBy;
use Lcobucci\JWT\Validation\Constraint\IssuedBy;
use Lcobucci\JWT\Validation\Constraint\PermittedFor;
use Lcobucci\JWT\ValidationData;

class JwtUtil
{
    // jwt github: https://github.com/lcobucci/jwt     https://jwt.io/
    protected $issuer = "http://example.com";
    protected $audience = "http://example.org";
    protected $id = "4f1g23a12aa11";
    // key 是绝对不允许泄露的
    protected static $key = "8swQsm1Xb0TA0Jw5ASPwClKVZPoTyS7GvhtaW0MxzKEihs1BNpcS2q3FYMJ11111";

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

        // 签发token, 设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、用户username、签名
        $token = $config->builder()
            ->issuedBy($this->issuer) // Configures the issuer (iss claim)
            ->permittedFor($this->audience) // Configures the audience (aud claim)
            ->identifiedBy($this->id, true) // Configures the id (jti claim), replicating as a header item
            ->issuedAt($time) // Configures the time that the token was issue (iat claim)
            ->canOnlyBeUsedAfter($time + 1) // Configures the time that the token can be used (nbf claim)  签发x秒钟后生效
            ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
            ->withClaim('uid', 20) // Configures a new claim, called "uid"
            ->withClaim('username', "Make") // Configures a new claim, called "uid"
            ->getToken($config->signer(), $config->signingKey()); // Retrieves the generated token
        return $token->toString();
    }

    /**
     * 验证 jwt token 并返回其中的用户id
     * verify token
     */
    public function verifyToken_bak($token)
{
        try {
            $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\StrictValidAt: ::验证存在及其有效性的权利要求中的iat,nbf和exp(支持余地配置
            //Lcobucci\JWT\Validation\Constraint\LooseValidAt: 验证的权利要求iat,nbf和exp,当存在时(支持余地配置)

            //验证jwt id是否匹配
            $validate_jwt_id = new IdentifiedBy($this->id);
            //验证签发人url是否正确
            $validate_issued = new IssuedBy($this->issuer);
            //验证客户端url是否匹配
            $validate_aud = new PermittedFor($this->audience);
            $config->setValidationConstraints($validate_jwt_id, $validate_issued, $validate_aud);

            $constraints = $config->validationConstraints();

            if (!$config->validator()->validate($token, ...$constraints)) {
                die("token invalid!");
            }
        } catch (\Exception $e) {
            die("error:" . $e->getMessage());
        }
        $jwtInfo = $token->claims();  // 这是jwt token中存储的所有信息
        return $jwtInfo->get("uid");  // 获取uid
    }

    /**
     * 加密解密使用的配置
     * @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(self::$key)
        // You may also override the JOSE encoder/decoder if needed by providing extra arguments here
        );
        return $configuration;
    }

    /**
     * 另一种验证方法,但是已经弃用
     * verify token
     */
    public function verifyToken($token)
{
        $token = (new Parser())->parse((string)$token);
        //验证token
        $data = new ValidationData();
        $data->setIssuer($this->issuer);//验证的签发人
        $data->setAudience($this->audience);//验证的接收人
        $data->setId($this->id);//验证token标识

        if (!$token->validate($data)) {
            //token验证失败
            die("token invalid!");
        }
        $jwtInfo = $token->claims();  // 这是jwt token中存储的所有信息
        return $jwtInfo->get("uid");  // 获取uid
    }

}



现在大家对于详解PHP实现JWT登录鉴权的过程是什么的内容应该都清楚了吧,希望大家阅读完这篇文章能有所收获。最后,想要了解更多详解PHP实现JWT登录鉴权的过程是什么的知识,欢迎关注群英网络,群英网络将为大家推送更多相关知识的文章。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: php
相关信息推荐
2022-09-19 17:57:59 
摘要:在之前的文章中我们已经了解了PHP的基础,其中就有$_GET 和 $_POST 变量,它们用来检索表单中的信息,其中需要我们注意的知识点就是PHP表单用户输入和表单验证。那接下来我们就来看一下PHP中表单输入与表单验证的相关知识吧。
2022-11-11 17:47:00 
摘要:strcat函数的作用:首先新建c语言的程序文件;然后用str函数复制一段话,将参数src字符串复制到参数dest所指的字符串尾部;最后使用strcat实现拼接字符串。
2022-05-11 11:32:20 
摘要:这篇文章主要介绍了Python数据可视化库Bokeh的使用总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部