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 高手之路(二)
Oct 09 PHP
php 数据库字段复用的基本原理与示例
Jul 22 PHP
php报表之jpgraph柱状图实例代码
Aug 22 PHP
php计算数组不为空元素个数的方法
Jan 27 PHP
Thinkphp自定义代码生成工具及用法说明(附下载地址)
May 27 PHP
zen cart实现订单中增加paypal中预留电话的方法
Jul 12 PHP
Laravel中间件实现原理详解
Oct 09 PHP
PHP基于正则批量替换Img中src内容实现获取缩略图的功能示例
Jun 07 PHP
PDO::query讲解
Jan 29 PHP
PHP使用Session实现上传进度功能详解
Aug 06 PHP
微信小程序发送订阅消息的方法(php 为例)
Oct 30 PHP
laravel5.6框架操作数据curd写法(查询构建器)实例分析
Jan 26 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
计算2000年01月01日起到指定日的天数
2006/10/09 PHP
ThinkPHP水印功能实现修复PNG透明水印并增加JPEG图片质量可调整
2014/11/05 PHP
ThinkPHP数据操作方法总结
2015/09/28 PHP
Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
2013/10/11 Javascript
JavaScript中的setUTCDate()方法使用详解
2015/06/11 Javascript
javascript获取本机操作系统类型的方法
2015/08/13 Javascript
深入浅析JavaScript中对事件的三种监听方式
2015/09/29 Javascript
微信小程序  网络请求API详解
2016/10/25 Javascript
原生js实现查询天气小应用
2016/12/09 Javascript
基于JavaScript实现带缩略图的轮播效果
2017/01/12 Javascript
Angular HMR(热模块替换)功能实现方法
2018/04/04 Javascript
引入外部js脚本加载慢与页面白屏问题的解决
2018/12/10 Javascript
JQuery判断radio单选框是否选中并获取值的方法
2019/01/17 jQuery
JS实现返回上一页并刷新页面的方法分析
2019/07/16 Javascript
JS实现可控制的进度条
2020/03/25 Javascript
python获取Linux下文件版本信息、公司名和产品名的方法
2014/10/05 Python
Python实现的简单文件传输服务器和客户端
2015/04/08 Python
连接Python程序与MySQL的教程
2015/04/29 Python
Python 基础知识之字符串处理
2017/01/06 Python
Python实现string字符串连接的方法总结【8种方式】
2018/07/06 Python
Python使用pymongo库操作MongoDB数据库的方法实例
2019/02/22 Python
PyQt5显示GIF图片的方法
2019/06/17 Python
python银行系统实现源码
2019/10/25 Python
20行Python代码实现视频字符化功能
2020/04/13 Python
捷克母婴用品购物网站:Feedo.cz
2020/12/28 全球购物
.NET初级开发工程师面试题(包括Javascript)
2012/08/22 面试题
外语专业毕业生个人的自荐信
2013/11/19 职场文书
建筑施工员岗位职责
2013/11/26 职场文书
电子商务个人自荐信
2013/12/12 职场文书
教导处工作制度
2014/01/18 职场文书
创建卫生先进单位实施方案
2014/03/10 职场文书
群众路线教育实践活动民主生活会个人检查对照思想汇报
2014/10/04 职场文书
2014年员工工作总结范文
2014/11/18 职场文书
MySQL令人咋舌的隐式转换
2021/04/05 MySQL
Python文件的操作示例的详细讲解
2021/04/08 Python
学习nginx基础知识
2021/09/04 Servers