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+MySql编写聊天室
Oct 09 PHP
学习使用curl采集curl使用方法
Jan 11 PHP
PHP 第一节 php简介
Apr 28 PHP
PHP生成验证码时“图像因其本身有错无法显示”的解决方法
Aug 07 PHP
PHP中shuffle数组值随便排序函数用法
Nov 21 PHP
PHP批量去除BOM头代码分享
Jun 26 PHP
Laravel实现自定义错误输出内容的方法
Oct 10 PHP
详解PHP中foreach的用法和实例
Oct 25 PHP
PHP实现的XML操作类【XML Library】
Dec 29 PHP
老生常谈php中传统验证与thinkphp框架(必看篇)
Jun 10 PHP
thinkPHP框架中layer.js的封装与使用方法示例
Jan 18 PHP
PHP count()函数讲解
Feb 03 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
Dedecms常用函数解析
2008/02/01 PHP
PHP 处理TXT文件(打开/关闭/检查/读取)
2013/05/13 PHP
php 获取SWF动画截图示例代码
2014/02/10 PHP
php读取富文本的时p标签会出现红线是怎么回事
2014/05/13 PHP
JavaScript实现删除电脑的关机键
2016/07/26 PHP
学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点)
2007/03/10 Javascript
JavaScript中的数组操作介绍
2014/12/30 Javascript
js结合正则实现国内手机号段校验
2015/06/19 Javascript
基于javascript实现图片懒加载
2016/01/05 Javascript
jQuery取得iframe中元素的常用方法详解
2016/01/14 Javascript
JavaScript实现点击单元格改变背景色的方法
2016/02/12 Javascript
快速解决js中window.location.href不工作的问题
2016/11/02 Javascript
jquery实现的table排序功能示例
2017/03/10 Javascript
jquery实现的放大镜效果示例
2020/02/24 jQuery
解决await在forEach中不起作用的问题
2021/02/25 Javascript
[16:27]DOTA2 HEROS教学视频教你分分钟做大人-艾欧
2014/06/11 DOTA
[40:56]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 Liquid vs TNC
2018/04/01 DOTA
python中定义结构体的方法
2013/03/04 Python
python有证书的加密解密实现方法
2014/11/19 Python
python urllib爬取百度云连接的实例代码
2017/06/19 Python
Python异常处理操作实例详解
2018/05/10 Python
Python基于百度云文字识别API
2018/12/13 Python
Python zip函数打包元素实例解析
2019/12/11 Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
2020/03/10 Python
Python unittest discover批量执行代码实例
2020/09/08 Python
匡威西班牙官网:Converse西班牙
2019/10/01 全球购物
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
服务员自我评价
2014/01/25 职场文书
高一学年自我鉴定范文(3篇)
2014/09/26 职场文书
共产党员批评与自我批评
2014/10/15 职场文书
领导个人查摆剖析材料
2014/10/29 职场文书
安全先进个人材料
2014/12/29 职场文书
九寨沟导游词
2015/02/02 职场文书
2015年幼儿园德育工作总结
2015/05/25 职场文书
《棉鞋里的阳光》教学反思
2016/02/20 职场文书
Django实现翻页的示例代码
2021/05/24 Python