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 相关文章推荐
简单易用的计数器(数据库)
Oct 09 PHP
PHP数组传递是值传递而非引用传递概念纠正
Jan 31 PHP
PHP获取ip对应地区和使用网络类型的方法
Mar 11 PHP
Yii2.0高级框架数据库增删改查的一些操作
Nov 16 PHP
关于php微信订阅号开发之token验证后自动发送消息给订阅号但是没有消息返回的问题
Dec 21 PHP
详解WordPress开发中过滤属性以及Sql语句的函数使用
Dec 25 PHP
浅谈PHP中的
Apr 23 PHP
php实现的debug log日志操作类实例
Jul 12 PHP
PHP基于Redis消息队列实现发布微博的方法
May 03 PHP
Yii2框架视图(View)操作及Layout的使用方法分析
May 27 PHP
laravel-admin解决表单select联动时,编辑默认没选上的问题
Sep 30 PHP
解决laravel查询构造器中的别名问题
Oct 17 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里的中文变量说明
2011/07/23 PHP
PHP实现的简单分页类及用法示例
2016/05/06 PHP
Yii2组件之多图上传插件FileInput的详细使用教程
2016/06/20 PHP
php结合ajax实现手机发红包的案例
2016/10/13 PHP
ThinkPHP框架实现的邮箱激活功能示例
2018/06/15 PHP
监控 url fragment变化的js代码
2010/04/19 Javascript
jquery实现居中弹出层代码
2010/08/25 Javascript
JS实现标签页效果(配合css)
2013/04/03 Javascript
关于jQuery新的事件绑定机制on()的使用技巧
2013/04/26 Javascript
Javascript合并表格中具有相同内容单元格示例
2013/08/11 Javascript
Javascript加载速度慢的解决方案
2014/03/11 Javascript
JS中如何判断传过来的JSON数据中是否存在某字段
2014/08/18 Javascript
PhotoShop给图片自动添加边框及EXIF信息的JS脚本
2015/02/15 Javascript
JS设置cookie、读取cookie
2016/02/24 Javascript
jQuery.ajax 跨域请求webapi设置headers的解决方案
2016/08/08 Javascript
js实现放大镜特效
2017/05/18 Javascript
JavaScript调用模式与this关键字绑定的关系
2018/04/21 Javascript
其实你可以少写点if else与switch(推荐)
2019/01/10 Javascript
Angular中使用ng-zorro图标库部分图标不能正常显示问题
2019/04/22 Javascript
VueCli3.0中集成MockApi的方法示例
2019/07/05 Javascript
Layui弹出层 加载 做编辑页面的方法
2019/09/16 Javascript
Bootstrap告警框(alert)实现弹出效果和短暂显示后上浮消失的示例代码
2020/08/27 Javascript
[40:13]Ti4 冒泡赛第二天 iG vs NEWBEE 2
2014/07/15 DOTA
python中urllib模块用法实例详解
2014/11/19 Python
Python实现爬取逐浪小说的方法
2015/07/07 Python
Python数据分析中Groupby用法之通过字典或Series进行分组的实例
2017/12/08 Python
Python Django简单实现session登录注销过程详解
2019/08/06 Python
django商品分类及商品数据建模实例详解
2020/01/03 Python
tensorflow estimator 使用hook实现finetune方式
2020/01/21 Python
小橄榄树:Le Petit Olivier
2018/04/23 全球购物
优秀党员获奖感言
2014/02/18 职场文书
大学生学习计划书
2014/09/15 职场文书
写给父母的感谢信
2015/01/22 职场文书
八年级历史教学反思
2016/02/19 职场文书
2019学校运动会开幕词
2019/05/13 职场文书
Java基础之this关键字的使用
2021/06/30 Java/Android