PHP JWT初识及示例

一直没有好好看过jwt,直到前两天要做web验证,朋友给我推荐了jwt。才发现jwt已经被大家广泛的应用了。看来我有点out了。哈哈,趁着这个世界来好好看看这个。

JWT(JSON Web Token), 顾名思义就是可以在Web上传输的token,这种token是用JSON格式进行format的。它是一个开源标准(RFC 7519),定义了一个紧凑的自包含的方式在不同实体之间安全的用JSON格式传输信息。

由于现在很多项目都是前后端分离,restful api模式。所以传统的session模式就没有办法满足认证需求,这个时候jwt的作用就来了。可以说 restful api认证是jwt的一个很好的应用场景。

参数解释

名称

解释

iss (issuer)

issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者

sub (Subject)

设置主题,类似于发邮件时的主题

aud (audience)

接收jwt的一方

exp (expire)

token过期时间

nbf (not before)

当前时间在nbf设定时间之前,该token无法使用

iat (issued at)

token创建时间

jti (JWT ID)

对当前token设置唯一标示

下面是一个很小的demo

require_once 'src/JWT.php';

header('Content-type:application/json');

//定义Key

const KEY = 'dasjdkashdwqe1213dsfsn;p';

$user = [

'uid'=>'dadsa-12312-vsd1s1-fsds',

'account'=>'daisc',

'password'=>'123456'

];

$redis = redis();

$action = $_GET['action'];

switch ($action)

{

case 'login':

login();

break;

case 'info':

info();

break;

}

//登陆,写入验证token

function login()

{

global $user;

$account = $_GET['account'];

$pwd = $_GET['password'];

$res = [];

if($account==$user['account']&&$pwd==$user['password'])

{

unset($user['password']);

$time = time();

$token = [

'iss'=>'http://test.cc',//签发者

'iat'=>$time,

'exp'=>$time+60,

'data'=>$user

];

$jwt = \Firebase\JWT\JWT::encode($token,KEY);

$res['code'] = 200;

$res['message'] = '登录成功';

$res['jwt'] = $jwt;

}

else

{

$res['message']= '用户名或密码错误';

$res['code'] = 401;

}

exit(json_encode($res));

}

function info()

{

$jwt = $_SERVER['HTTP_AUTHORIZATION'] ?? false;

$res['code'] = 200;

if($jwt)

{

$jwt = str_replace('Bearer ','',$jwt);

if(empty($jwt))

{

$res['code'] = 401;

$res['msg'] = 'You do not have permission to access.';

exit(json_encode($res));

}

try{

$token = (array) \Firebase\JWT\JWT::decode($jwt,KEY, ['HS256']);

if($token['exp']

{

$res['code'] = 401;

$res['msg'] = '登录超时,请重新登录';

}

$res['data']= $token['data'];

}catch (\Exception $E)

{

$res['code'] = 401;

$res['msg'] = '登录超时,请重新登录.';

}

}

else

{

$res['code'] = 401;

$res['msg'] = 'You do not have permission to access.';

}

exit(json_encode($res));

}

//连接redis

function redis()

{

$redis = new Redis();

$redis->connect('127.0.0.1');

return $redis;

}

这个dmeo里面用jwt做了一个简单的认证。 其中用到了一个php-jwt的加密包https://github.com/firebase/php-jwt

其中KEY为定义的私钥也就是jwt里面的 sign部分,这个一定要保存好。

而header部分php-jwt包里面已经帮我们完成了,加密代码如下

public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)

{

$header = array('typ' => 'JWT', 'alg' => $alg);

if ($keyId !== null) {

$header['kid'] = $keyId;

}

if ( isset($head) && is_array($head) ) {

$header = array_merge($head, $header);

}

$segments = array();

$segments[] = static::urlsafeB64Encode(static::jsonEncode($header));

$segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));

$signing_input = implode('.', $segments);

$signature = static::sign($signing_input, $key, $alg);

$segments[] = static::urlsafeB64Encode($signature);

return implode('.', $segments);

}

可以看出默认的加密的方式是HS256。这也是说jwt安全的原因。现阶段HS256加密还是很安全的。

这个包里面也支持证书加密。

加密解密的过程这个包已经帮我们完成了。所以我们只需要定义jwt中的 poyload部分就可以了。也就是demo里面的token部分。加密成功会得到一个加密的Jwt字符串,下次前端在请求api的时候需要携带这个jwt字符串作为认证。

在header头里面增加Authorization。在服务端验证的时候回通过取得这个值来验证回话的有效。

下面是poyload的一些常用配置

$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",

];

里面包含的配置可以自由配置,也可以自己添加一些其他的。这些都是网上大家常用的,可以说是一种约定吧。

注意事项

关于jwt的使用大概就是这些。上面的代码在你使用的时候可能会出现两个问题:

1、命名空间错误

解决:不使用命名空间的话,使用require引入文件。如果使用命名空间出现错误,请检查命名空间的路径。

2、生成的token是一个对象

解决:(string)$token 将token强转成string

php 后端实现JWT认证方法示例

JWT是什么

JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。基于token的身份验证可以替代传统的cookie+session身份验证方法。

它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。它具备两个特点:

简洁(Compact):可以通过URL, POST 参数或者在 HTTP header 发送,因为数据量小,传输速度快

自包含(Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库

JWT由三个部分组成:header.payload.signature

以下示例以JWT官网为例

header部分:

{

"alg": "HS256",

"typ": "JWT"

}

对应base64UrlEncode编码为:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

说明:该字段为json格式。alg字段指定了生成signature的算法,默认值为HS256,typ默认值为JWT

payload部分:

{

"sub": "1234567890",

"name": "John Doe",

"iat": 1516239022

}

对应base64UrlEncode编码为:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

说明:该字段为json格式,表明用户身份的数据,可以自己自定义字段,很灵活。sub 面向的用户,name 姓名 ,iat 签发时间。例如可自定义示例如下:

{

"iss": "admin", //该JWT的签发者

"iat": 1535967430, //签发时间

"exp": 1535974630, //过期时间

"nbf": 1535967430, //该时间之前不接收处理该Token

"sub": "www.admin.com", //面向的用户

"jti": "9f10e796726e332cec401c569969e13e" //该Token唯一标识

}

signature部分:

HMACSHA256(

base64UrlEncode(header) + "." +

base64UrlEncode(payload),

123456

)

对应的签名为:keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

最终得到的JWT的json为(header.payload.signature):eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.keH6T3x1z7mmhKL1T3r9sQdAxxdzB6siemGMr_6ZOwU

说明:对header和payload进行base64UrlEncode编码后进行拼接。通过key(这里是123456)进行HS256算法签名。

JWT使用流程

初次登录:用户初次登录,输入用户名密码

密码验证:服务器从数据库取出用户名和密码进行验证

生成JWT:服务器端验证通过,根据从数据库返回的信息,以及预设规则,生成JWT

返还JWT:服务器的HTTP RESPONSE中将JWT返还

带JWT的请求:以后客户端发起请求,HTTP REQUEST

HEADER中的Authorizatio字段都要有值,为JWT

服务器验证JWT

PHP如何实现JWT

作者使用的是PHP 7.0.31,不废话,直接上代码,新建jwt.php,复制粘贴如下:

/**

* PHP实现jwt

*/

class Jwt {

//头部

private static $header=array(

'alg'=>'HS256', //生成signature的算法

'typ'=>'JWT' //类型

);

//使用HMAC生成信息摘要时所使用的密钥

private static $key='123456';

/**

* 获取jwt token

* @param array $payload jwt载荷 格式如下非必须

* [

* 'iss'=>'jwt_admin', //该JWT的签发者

* 'iat'=>time(), //签发时间

* 'exp'=>time()+7200, //过期时间

* 'nbf'=>time()+60, //该时间之前不接收处理该Token

* 'sub'=>'www.admin.com', //面向的用户

* 'jti'=>md5(uniqid('JWT').time()) //该Token唯一标识

* ]

* @return bool|string

*/

public static function getToken(array $payload)

{

if(is_array($payload))

{

$base64header=self::base64UrlEncode(json_encode(self::$header,JSON_UNESCAPED_UNICODE));

$base64payload=self::base64UrlEncode(json_encode($payload,JSON_UNESCAPED_UNICODE));

$token=$base64header.'.'.$base64payload.'.'.self::signature($base64header.'.'.$base64payload,self::$key,self::$header['alg']);

return $token;

}else{

return false;

}

}

/**

* 验证token是否有效,默认验证exp,nbf,iat时间

* @param string $Token 需要验证的token

* @return bool|string

*/

public static function verifyToken(string $Token)

{

$tokens = explode('.', $Token);

if (count($tokens) != 3)

return false;

list($base64header, $base64payload, $sign) = $tokens;

//获取jwt算法

$base64decodeheader = json_decode(self::base64UrlDecode($base64header), JSON_OBJECT_AS_ARRAY);

if (empty($base64decodeheader['alg']))

return false;

//签名验证

if (self::signature($base64header . '.' . $base64payload, self::$key, $base64decodeheader['alg']) !== $sign)

return false;

$payload = json_decode(self::base64UrlDecode($base64payload), JSON_OBJECT_AS_ARRAY);

//签发时间大于当前服务器时间验证失败

if (isset($payload['iat']) && $payload['iat'] > time())

return false;

//过期时间小宇当前服务器时间验证失败

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

return false;

//该nbf时间之前不接收处理该Token

if (isset($payload['nbf']) && $payload['nbf'] > time())

return false;

return $payload;

}

/**

* base64UrlEncode https://jwt.io/ 中base64UrlEncode编码实现

* @param string $input 需要编码的字符串

* @return string

*/

private static function base64UrlEncode(string $input)

{

return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));

}

/**

* base64UrlEncode https://jwt.io/ 中base64UrlEncode解码实现

* @param string $input 需要解码的字符串

* @return bool|string

*/

private static function base64UrlDecode(string $input)

{

$remainder = strlen($input) % 4;

if ($remainder) {

$addlen = 4 - $remainder;

$input .= str_repeat('=', $addlen);

}

return base64_decode(strtr($input, '-_', '+/'));

}

/**

* HMACSHA256签名 https://jwt.io/ 中HMACSHA256签名实现

* @param string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)

* @param string $key

* @param string $alg 算法方式

* @return mixed

*/

private static function signature(string $input, string $key, string $alg = 'HS256')

{

$alg_config=array(

'HS256'=>'sha256'

);

return self::base64UrlEncode(hash_hmac($alg_config[$alg], $input, $key,true));

}

}

//测试和官网是否匹配begin

$payload=array('sub'=>'1234567890','name'=>'John Doe','iat'=>1516239022);

$jwt=new Jwt;

$token=$jwt->getToken($payload);

echo "

";

echo $token;

//对token进行验证签名

$getPayload=$jwt->verifyToken($token);

echo "
";

var_dump($getPayload);

echo "
";

//测试和官网是否匹配end

//自己使用测试begin

$payload_test=array('iss'=>'admin','iat'=>time(),'exp'=>time()+7200,'nbf'=>time(),'sub'=>'www.admin.com','jti'=>md5(uniqid('JWT').time()));;

$token_test=Jwt::getToken($payload_test);

echo "

";

echo $token_test;

//对token进行验证签名

$getPayload_test=Jwt::verifyToken($token_test);

echo "
";

var_dump($getPayload_test);

echo "
";

//自己使用时候end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持码农之家。

以上就是本次给大家分享的关于java的全部知识点内容总结,大家还可以在下方相关文章里找到相关文章进一步学习,感谢大家的阅读和支持。

php jwt使用案例,PHP JWT基础知识及其简单示例相关推荐

  1. 在ASP.NET Atlas中调用Web Service——创建Mashup调用远端Web Service(基础知识以及简单示例)...

    作者:Dflying Chen (http://dflying.cnblogs.com/) 注:Atlas中的Mashup极其复杂,其中涉及众多的对象与架构,为了写这篇文章,我花了不少时间学习研究.同 ...

  2. 计算机网络应用最简单的,计算机网络的基础知识和简单应用.ppt

    文档介绍: 第8章计算机网络的基础知识和简单应用学****内容:计算机网络基本概念;因特网初步;因特网的服务功能.泊罩制藩往巍趋态拯巧郸嘘橡唤姬恍退戏付永缺彪崭嘶律旁炸雹蜡溪大相计算机网络的基础知识和 ...

  3. 伺服的基础知识及简单应用

    文章目录 伺服的基础知识及简单应用 伺服基础知识 什么是伺服 伺服电机的种类 编码器种类 伺服的原理和构成 伺服的控制环 编码器的基础知识 编码器的分类及工作原理 光电增量式编码器 光电绝对式编码器 ...

  4. 计算机打单基础知识,电脑基础知识:简单认识打印机及耗材

    原标题:电脑基础知识:简单认识打印机及耗材 打印机(Printer) 是计算机的输出设备之一,用于将计算机处理结果打印在相关介质上. 这里先讲讲我们日常办公接触最多的桌面打印机:分为针式打印机,喷墨式 ...

  5. Java提取文本文档中的所有网址(小案例介绍正则基础知识)

    正则表达式基础以及Java中使用正则查找 定义: 正则表达式是一些用来匹配和处理文本的字符串 正则的基础(先大致了解下) 1. 正则表达式的作用 查找特定的信息(搜索) 替换一些文本(替换) 2. 正 ...

  6. 前端基础知识与简单模板

    vue知识总结 基础知识文档 vue.js搭建个人博客 vue写的一些小网站 个人网站的开发之路 Vue.js技术揭秘 vue基础知识 基础项目 vue前端开发学习 基础的 vue的js代码使用方法 ...

  7. dreamwever基础知识与简单网页的制作

    Dreamweaver 简单网页的基础知识(一) 1.HTML简单理解: 2.内部样式表和内联样式表的区别 3.dreamweaver常用代码注释 4.CSS语法 5.CSS 选择器 5.选择器的组合 ...

  8. python 概率分布类型检验_统计学:假设检验Python案例实现+概率论基础知识回顾...

    先通过一个案例说明单样本检验的过程: 案例分析: 公司制造出10台引擎供测试使用,每一台的排放水平如下: 15.6 16.2 22.5 20.5 16.4 19.4 16.6 17.9 12.7 13 ...

  9. matlab基础知识与简单操作

    目录 1.常识 2.数组的使用 3.矩阵基础运算 4.数据和函数的可视化 5.Matlab程序设计 6.求解线性方程组 7.曲线拟合 8.曲线差值 9.符号计算 10.简单练习 1.常识 %pi是系统 ...

最新文章

  1. 京瓷2010复印a4内容不全_百万畅销书活法的原点,稻盛和夫从未公开的京瓷秘籍...
  2. Gentoo 安装日记 13 (配置内核 :可执行文件安格式和网络)
  3. 在理解通用近似定理之前,你可能都不会理解神经网络
  4. 打印机打印网页不清晰_针式打印机不开机故障维修
  5. 前端学习(1601):状态提升
  6. php输入多少数值自动乘,报表数据填报中的自动计算
  7. ZK 数据传输三:在页面使用SpringUtil获取spring层类再获取数据(jsp页面或zul页面)...
  8. Turbo码编码举例计算
  9. 物联lot是什么意思_什么是物联网,物联网(lOT)简介
  10. 南京大学计算机学院2019调剂,2019年南京大学考研调剂相关规定
  11. 程序员被拖欠工资欲删库跑路,网友:还有没有职业素养
  12. Jupyter notebook的主题和字体美化
  13. unix/Linux常用命令英文全称与中文解释 man ,su,ps,ls 等等
  14. 中央农村工作会议释放重要信号,AI 技术助力农业的十种路径,未来可期
  15. 交房后,如何办理产权证、土地证?
  16. DPU网络开发SDK—DPDK(八)
  17. 电气比例阀外接压力传感器和PID控制器实现微正压0.1%的超高精度控制
  18. 搜索请求实体(Request Body Search)
  19. 分享5个宝藏小网站,工作学习都能用到
  20. 20221210英语学习

热门文章

  1. allegro-Could not create new pin inst: PA15/JTDI.
  2. 线性dp——hdu6578经典dp
  3. 基于python数据分析(分析篇七:预测/误差)
  4. WIN10 时间同步
  5. 基于51单片机的频率计
  6. 人群捕捞:你的隐私无处遁形
  7. 苹果id提示购买无法完成怎么办?
  8. 游戏编程学Python(8)— 扫雷(文字版)
  9. 大华摄像头网页端控制+web串口(适用任何浏览器,不能用来打我)通讯合集
  10. 国内外vps有什么区别?