解释JWT
JWT是一个字符串,经过加密和验证,由三部分组成。基于令牌的身份验证可以取代传统的cookie会话身份验证方法。这三个部分如下:
Header.payload.signatureheader
标题格式为:
{'typ' :' jwt ',' alg' :' HS256'}这是一个json字符串,两个字段都是必需的。alg字段指定生成签名的算法,默认值为hs256。您可以指定其他加密算法,例如RSA。您可以通过base64encode获取标头。
有效载荷分量
playload的基本组件:
简单点:
$ payload=[' ISS '=$发卡行,//发卡行' IAT'=$ _ server ['request _ time'],//它是什么时候发出的' exp '=$ _ server[' request _ time ']7200//到期时间' uid'=1111]复杂性:正式来说,它由三个部分组成(保留声明,公共声明,私有声明)
$token=[#不是必需的。发布者请求实体可以是发起请求的用户的信息,也可以是jwt的发布者。Iss'='http://example.org ',#不是必需的。发布于.令牌创建时间,unix时间戳格式' IAT'=$ _ server ['request _ time'],#不是必需的。Expire指定令牌的生命周期。Unix时间戳格式' exp '=$ _ server[' request _ time ']7200,#不是必需的。接收JWT的一方。Aud'='http://example.com ',#不是必需的。不需要此JWT #所针对的用户“sub”=“[电子邮件保护]”。以前没有.如果当前时间早于nbf中的时间,令牌将不被接受;一般都会留一些余地,比如几分钟。Nbf'=1357000000,#不是必需的。JWT身份证.当前令牌' jti'='222we ',#自定义字段' GivenName'='Jonny ',#自定义字段' name'='Rocket ',#自定义字段' Email'='[emailprotected]',];有效载荷也是一个json数据,它指示用户的身份。它可以自定义自己的字段,非常灵活。您也可以简单地使用它,例如以简单的方式。有效载荷可以通过json_encode和base64_encode获得
签名的一部分
使用报头中指定的加密算法加密报头和有效负载。当然,你需要在加密过程中自定义密钥,所以你可以自己选择一个字符串。官网示例:
Hmacsha256 (base64 urlencode(标头)'.'base64 urlencode(有效负载,秘密)是自己使用的:
?php公共静态函数encode(array $payload,string $key,string $ alg=' sha 256 '){ $ key=MD5($ key);$ jwt=self : urlsafeb64 encode(JSON _ encode([' typ '=' JWT ',' alg'=$alg])。'.'。self : urlsafeb64 encode(JSON _ encode($ payload));返回$jwt。'.'。self:signature($jwt,$key,$ alg);}公共静态函数签名(string $input,string $key,string $ alg){ return hash _ hmac($ alg,$input,$ key);}使用这三个部分。当它们连接在一起时,它们就是高个子上的JWT,然后它们就可以使用了。
JWT使用过程
官方使用流程描述:
翻译一下:
首次登录:用户首次登录,输入用户名和密码进行密码认证:服务器从数据库中取出用户名和密码进行认证,生成JWT;根据数据库返回的信息和预设规则,生成JWT返回JWT;在服务器的HTTP响应中返回JWT对JWT的请求;当客户端将来发起请求时,HTTP REQUEST HEADER中的Authorizatio字段必须有一个值,这就是JWTJWT身份验证过程
因为是我自己写的,没有使用框架,所以还是要简单记录验证过程
客户端在请求头中携带JWT信息,后端获得$ _ server[http _ authorization]:
但是,请注意,我没有在此授权中添加持有人。来人是公务用的,你可以自己用:
授权:承载令牌PHP认证伪码:
?phppublic静态函数decode(string $jwt,string $ key){ $ token=explode(' . ',$ jwt);$ key=MD5($ key);if(计数($ tokens)!=3)返回falselist($header64,$payload64,$ sign)=$ token;$ header=JSON _ decode(self :3360 urlsafeb64 decode($ header 64),JSON _ OBJECT _ AS _ ARRAY);if(空($header['alg']))返回falseif(self :3360 signature($ header 64。'.'。$payload64,$key,$header['alg'])!==$sign)返回false$ payload=JSON _ decode(self :3360 urlsafeb64 decode($ payload 64),JSON _ OBJECT _ AS _ ARRAY);$ TIME=$ _ SERVER[' REQUEST _ TIME '];if(isset($ payload[' IAT '])$ payload[' IAT ']$ time)返回falseif(isset($ payload[' exp '])$ payload[' exp ']$ time)返回false返回$有效载荷;}公共静态函数urlsafeB64Decode(字符串$ input){ $余数=strlen($ input)% 4;if($余数){ $ pad len=4-$余数;$输入。=str_repeat('=',$ pad len);}返回base64_decode(strtr($input,'-_ ','/');}公共静态函数urlsafeb64 encode(string $ input){ return str _ replace('=','',strtr(base64_encode($input),'/','-_ ');}使用}JWT的注意事项
对于JWT,我们一般考虑两点:
1.签名正确吗?
2.代币过期了吗?
这两个块可以通过检查几个字段来处理
1.建立令牌撤销机制,将令牌写入数据库,
2.无效令牌。因为它没有进入数据库,所以可以确定传递的令牌是有效的。
3.验证有效令牌的签名,获取令牌后重新生成签名,验证令牌的签名部分(C位的值)是否一致。
4.要确认令牌是否已超时,您可以通过exp(过期)指定令牌的生命周期。Unix时间戳格式)和nbf(以前没有。如果当前时间早于nbf中的时间,则令牌将不被接受。Unix时间戳格式。),获取令牌后,判断时间。
5.为了防止重放攻击,可以添加iss(发卡行请求实体),它可以是发起请求的用户或jwt的发卡行的信息。),jti (JWT身份证.当前令牌的唯一标识符)和iat(颁发于)。令牌创建时间,unix时间戳格式),然后在获取令牌后,匹配声明信息。
参考文章:
https://jwt.io/introduction/
https://www.jb51.net/article/146963.htm
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。