基于PHP怎么实现JWT登录鉴权

基于PHP怎么实现JWT登录鉴权

本文小编为大家详细介绍“基于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、引入依赖

composerrequirelcobucci/jwt3.*

2、功能实现

  • 签发token, 设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、用户username、签名。其中,用户id、用户username是特意存储在token中的信息,也可以增加一些其他信息,这样在解析的时候就可以直接获取到这些信息,不能是敏感数据

  • 验证令牌验证这个Token是不是合法的,有没有过期等,并可以解析出subject和claim里面的数据,传递jwt token的方式为Authorization中的Bearer Token,如下

3、封装工具类如下

<?php/***CreatedbyPhpStorm*@authorsxd*/namespaceApp\Utils;useLcobucci\JWT\Configuration;useLcobucci\JWT\Parser;useLcobucci\JWT\Signer\Hmac\Sha256;useLcobucci\JWT\Signer\Key\InMemory;useLcobucci\JWT\Token\Plain;useLcobucci\JWT\Validation\Constraint\IdentifiedBy;useLcobucci\JWT\Validation\Constraint\IssuedBy;useLcobucci\JWT\Validation\Constraint\PermittedFor;useLcobucci\JWT\ValidationData;classJwtUtil{//jwtgithub:https://github.com/lcobucci/jwthttps://jwt.io/protected$issuer="http://example.com";protected$audience="http://example.org";protected$id="4f1g23a12aa11";//key是绝对不允许泄露的protectedstatic$key="8swQsm1Xb0TA0Jw5ASPwClKVZPoTyS7GvhtaW0MxzKEihs1BNpcS2q3FYMJ11111";/***签发令牌*/publicfunctiongetToken(){$time=time();$config=self::getConfig();assert($configinstanceofConfiguration);//签发token,设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、用户username、签名$token=$config->builder()->issuedBy($this->issuer)//Configurestheissuer(issclaim)->permittedFor($this->audience)//Configurestheaudience(audclaim)->identifiedBy($this->id,true)//Configurestheid(jticlaim),replicatingasaheaderitem->issuedAt($time)//Configuresthetimethatthetokenwasissue(iatclaim)->canOnlyBeUsedAfter($time+1)//Configuresthetimethatthetokencanbeused(nbfclaim)签发x秒钟后生效->expiresAt($time+3600)//Configurestheexpirationtimeofthetoken(expclaim)->withClaim('uid',20)//Configuresanewclaim,called"uid"->withClaim('username',"Make")//Configuresanewclaim,called"uid"->getToken($config->signer(),$config->signingKey());//Retrievesthegeneratedtokenreturn$token->toString();}/***验证jwttoken并返回其中的用户id*verifytoken*/publicfunctionverifyToken_bak($token){try{$config=self::getConfig();assert($configinstanceofConfiguration);$token=$config->parser()->parse($token);assert($tokeninstanceofPlain);//Lcobucci\JWT\Validation\Constraint\IdentifiedBy:验证jwtid是否匹配//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,当存在时(支持余地配置)//验证jwtid是否匹配$validate_jwt_id=newIdentifiedBy($this->id);//验证签发人url是否正确$validate_issued=newIssuedBy($this->issuer);//验证客户端url是否匹配$validate_aud=newPermittedFor($this->audience);$config->setValidationConstraints($validate_jwt_id,$validate_issued,$validate_aud);$constraints=$config->validationConstraints();if(!$config->validator()->validate($token,...$constraints)){die("tokeninvalid!");}}catch(\Exception$e){die("error:".$e->getMessage());}$jwtInfo=$token->claims();//这是jwttoken中存储的所有信息return$jwtInfo->get("uid");//获取uid}/***加密解密使用的配置*@returnConfiguration*/publicstaticfunctiongetConfig(){$configuration=Configuration::forSymmetricSigner(//YoumayuseanyHMACvariations(256,384,and512)newSha256(),//replacethevaluebelowwithakeyofyourown!InMemory::base64Encoded(self::$key)//YoumayalsooverridetheJOSEencoder/decoderifneededbyprovidingextraargumentshere);return$configuration;}/***另一种验证方法,但是已经弃用*verifytoken*/publicfunctionverifyToken($token){$token=(newParser())->parse((string)$token);//验证token$data=newValidationData();$data->setIssuer($this->issuer);//验证的签发人$data->setAudience($this->audience);//验证的接收人$data->setId($this->id);//验证token标识if(!$token->validate($data)){//token验证失败die("tokeninvalid!");}$jwtInfo=$token->claims();//这是jwttoken中存储的所有信息return$jwtInfo->get("uid");//获取uid}}

读到这里,这篇“基于PHP怎么实现JWT登录鉴权”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注恰卡编程网行业资讯频道。

发布于 2022-04-15 22:32:17
收藏
分享
海报
0 条评论
38
上一篇:springboot图片验证码功能模块怎么实现 下一篇:C++模板使用实例分析
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码