php JWT在web端中的使用方法教程


Posted in PHP onSeptember 06, 2018

解释一下JWT

JWT就是一个字符串,经过加密处理与校验处理的字符串,由三个部分组成。基于token的身份验证可以替代传统的cookie+session身份验证方法。三个部分分别如下:

header.payload.signature

header部分组成

header 格式为:

{
"typ":"JWT",
"alg":"HS256"
}

这就是一个json串,两个字段都是必须的,alg字段指定了生成signature的算法,默认值为 HS256,可以自己指定其他的加密算法,如RSA.经过base64encode就可以得到 header.

payload 部分组成

playload 基本组成部分:

简单点:

$payload=[
  'iss' => $issuer, //签发者
  'iat' => $_SERVER['REQUEST_TIME'], //什么时候签发的
  'exp' => $_SERVER['REQUEST_TIME'] + 7200 //过期时间
  'uid'=>1111
 ];

复杂点:官方说法,三个部分组成(Reserved claims,Public claims,Private claims)

$token = [
  #非必须。issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者。
  "iss" => "http://example.org",
  #非必须。issued at。 token创建时间,unix时间戳格式
  "iat" => $_SERVER['REQUEST_TIME'],
  #非必须。expire 指定token的生命周期。unix时间戳格式
  "exp" => $_SERVER['REQUEST_TIME'] + 7200,
  #非必须。接收该JWT的一方。
  "aud" => "http://example.com",
  #非必须。该JWT所面向的用户
  "sub" => "jrocket@example.com",
  # 非必须。not before。如果当前时间在nbf里的时间之前,则Token不被接受;一般都会留一些余地,比如几分钟。
  "nbf" => 1357000000,
  # 非必须。JWT ID。针对当前token的唯一标识
  "jti" => '222we',
  # 自定义字段
  "GivenName" => "Jonny",
  # 自定义字段
  "name" => "Rocket",
  # 自定义字段
  "Email" => "jrocket@example.com",
  
 ];

payload 也是一个json数据,是表明用户身份的数据,可以自己自定义字段,很灵活。你也可以简单的使用,比如简单的方式。经过json_encode和base64_encode就可得到payload

signature组成部分

将 header和 payload使用header中指定的加密算法加密,当然加密过程还需要自定秘钥,自己选一个字符串就可以了。
官网实例:

HMACSHA256(
 base64UrlEncode(header) + "." +
 base64UrlEncode(payload),
 secret)

自己使用:

<?php

 public static function encode(array $payload, string $key, string $alg = 'SHA256')
 {
 $key = md5($key);
 $jwt = self::urlsafeB64Encode(json_encode(['typ' => 'JWT', 'alg' => $alg])) . '.' . self::urlsafeB64Encode(json_encode($payload));
 return $jwt . '.' . self::signature($jwt, $key, $alg);
 }

 public static function signature(string $input, string $key, string $alg)
 {
 return hash_hmac($alg, $input, $key);
 }

这三个部分使用.连接起来就是高大上的JWT,然后就可以使用了.

JWT使用流程

官方使用流程说明:

php JWT在web端中的使用方法教程

翻译一下:

  • 初次登录:用户初次登录,输入用户名密码
  • 密码验证:服务器从数据库取出用户名和密码进行验证
  • 生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT
  • 返还JWT:服务器的HTTP RESPONSE中将JWT返还
  • 带JWT的请求:以后客户端发起请求,HTTP REQUEST HEADER中的Authorizatio字段都要有值,为JWT

JWT 验证过程

因为自己写的,没有使用框架,所以还是得简单记录一下验证过程

客户端在请求头中带有JWT信息,后端获取$_SERVER[HTTP_AUTHORIZATION]:

php JWT在web端中的使用方法教程

不过注意一点,我这个Authorization没有加Bearer,官方使用中就使用了Bearer,你也可以自己使用:

Authorization: Bearer <token>

php 验证伪代码:

<?php
public static function decode(string $jwt, string $key)
 {
  $tokens = explode('.', $jwt);
  $key = md5($key);

  if (count($tokens) != 3)
   return false;

  list($header64, $payload64, $sign) = $tokens;

  $header = json_decode(self::urlsafeB64Decode($header64), JSON_OBJECT_AS_ARRAY);
  if (empty($header['alg']))
   return false;

  if (self::signature($header64 . '.' . $payload64, $key, $header['alg']) !== $sign)
   return false;

  $payload = json_decode(self::urlsafeB64Decode($payload64), JSON_OBJECT_AS_ARRAY);

  $time = $_SERVER['REQUEST_TIME'];
  if (isset($payload['iat']) && $payload['iat'] > $time)
   return false;

  if (isset($payload['exp']) && $payload['exp'] < $time)
   return false;

  return $payload;
 }

 public static function urlsafeB64Decode(string $input)
 {
  $remainder = strlen($input) % 4;

  if ($remainder)
  {
   $padlen = 4 - $remainder;
   $input .= str_repeat('=', $padlen);
  }

  return base64_decode(strtr($input, '-_', '+/'));
 }
 
 
  public static function urlsafeB64Encode(string $input)
 {
  return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
 }

JWT 在使用中的注意事项

使用了 JWT 我们一般都会考虑两点:

1. 签名是否正确?

2. Token是否到期?

这两块可以通过校验几个字段来处理

1. 建立 token 吊销机制,将 token 写入数据库,

2. 无效 token 因未入数据库,所以确信传入的 token 是有效的。

3. 对有效的 token 进行签名验证,获取到 token 后重新生成签名进行校验 token 的签名部分( C 位的值)是否一致。

4. 确认是否 token 超时可以通过 exp(expire 指定token的生命周期。unix时间戳格式) 和 nbf(not before。如果当前时间在nbf里的时间之前,则Token不被接受。unix时间戳格式。) 声明,获取到 token 后,对时间进行判断。

5. 为了防止replay attack,可加上 iss(issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者。),jti (JWT ID。针对当前token的唯一标识) 和 iat(issued at。 token创建时间,unix时间戳格式) 声明,然后获取到 token 后,对声明信息进行匹配。

参考文章:

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
关于PHP模板Smarty的初级使用方法以及心得分享
Jun 21 PHP
深入PHP许愿墙模块功能分析
Jun 25 PHP
PHP文件上传问题汇总(文件大小检测、大文件上传处理)
Dec 24 PHP
PHP缓冲区用法总结
Feb 14 PHP
解读PHP中上传文件的处理问题
May 29 PHP
PHP微信刮刮卡 附微信接口
Jul 22 PHP
php简单截取字符串代码示例
Oct 19 PHP
php实现用户注册密码的crypt加密
Jun 08 PHP
php生成二维码不保存服务器还有下载功能的实现代码
Aug 09 PHP
PHP抽象类基本用法示例
Dec 28 PHP
Thinkphp整合阿里云OSS图片上传实例代码
Apr 28 PHP
PHP设计模式(三)建造者模式Builder实例详解【创建型】
May 02 PHP
php进程daemon化的正确实现方法
Sep 06 #PHP
让Laravel API永远返回JSON格式响应的方法示例
Sep 05 #PHP
thinkPHP框架实现类似java过滤器的简单方法示例
Sep 05 #PHP
PHP使用pdo实现事务处理操作示例
Sep 05 #PHP
Django 标签筛选的实现代码(一对多、多对多)
Sep 05 #PHP
利用PHP扩展Xhprof分析项目性能实践教程
Sep 05 #PHP
PHP时间处理类操作示例
Sep 05 #PHP
You might like
最令PHP初学者头痛的十四个问题
2006/07/12 PHP
一个数据采集类
2007/02/14 PHP
PHP中数组的三种排序方法分享
2012/05/07 PHP
php中fgetcsv()函数用法实例
2014/11/28 PHP
浅谈PHP的exec()函数无返回值排查方法(必看)
2017/03/31 PHP
jquery向.ashx文件post中文乱码问题的解决方法
2011/03/28 Javascript
将中国标准时间转换成标准格式的代码
2014/03/20 Javascript
AngularJS ng-bind-template 指令详解
2016/07/30 Javascript
微信小程序实现文字无限轮播效果
2018/12/28 Javascript
JavaScript基于遍历操作实现对象深拷贝功能示例
2019/03/05 Javascript
原生js基于canvas实现一个简单的前端截图工具代码实例
2019/09/10 Javascript
jquery实现上传图片功能
2020/06/29 jQuery
JavaScript数组常用的增删改查与其他属性详解
2020/10/13 Javascript
详细解析Python当中的数据类型和变量
2015/04/25 Python
Python3实现发送QQ邮件功能(文本)
2017/12/15 Python
python使用writerows写csv文件产生多余空行的处理方法
2019/08/01 Python
python实现拉普拉斯特征图降维示例
2019/11/25 Python
解决c++调用python中文乱码问题
2020/07/29 Python
python使用建议与技巧分享(二)
2020/08/17 Python
Python3+SQLAlchemy+Sqlite3实现ORM教程
2021/02/16 Python
python源文件的字符编码知识点详解
2021/03/04 Python
德国汉莎航空中国官网: Lufthansa中国
2017/03/30 全球购物
生物有机护肤品:Aurelia Probiotic Skincare
2018/01/31 全球购物
园林资料员岗位职责
2013/12/30 职场文书
人力资源经理自我评价
2014/01/04 职场文书
校园达人秀策划书
2014/01/12 职场文书
2014年毕业演讲稿范文
2014/05/13 职场文书
药剂专业自荐书
2014/06/20 职场文书
建筑节能汇报材料
2014/08/22 职场文书
办公室领导干部作风整顿个人整改措施
2014/09/17 职场文书
甜品蛋糕店创业计划书
2014/09/21 职场文书
2015年信息技术教研组工作总结
2015/07/22 职场文书
2016婚礼主持词开场白
2015/11/24 职场文书
企业管理制度设计时要注意的几种“常见病”!
2019/04/19 职场文书
2019开业庆典剪彩仪式主持词!
2019/07/22 职场文书
导游词之麻姑仙境
2019/11/18 职场文书