PHP如何使用JWT做Api接口身份认证的实现


Posted in PHP onFebruary 03, 2020

1.JWT是什么?

JWT官网 https://jwt.io

官网简介:JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对对JWT进行签名。
通常来说,JWT是一个由包含用户信息所生成的加密串,将生成的JWT加密串放入所有的请求head中,前端通过设定的秘钥加密参数,发送数据给后端,后端接收参数,按照设定的秘钥,同样加密接收参数,与前端加密参数做比对,保证请求有效并防止参数不被篡改。验证通过就进行相关的逻辑处理,否则请求算作无效请求。

2.为什么使用JWT?

传统互联网项目在实现保持登录状态、退出登录、接口请求等功能时会使用Session,但是众所周知Session数据在产生后会存储与服务器端,所以当用户量达到一定程度会相应影响到服务器的性能,且Session在前后端分离的项目中或是多服务器项目中的支持不是很好。但是Token不会产生这些问题,服务器端对Token只有生成和验证操作,不会存放数据,针对前后端分离的项目,包括手机APP和当前热门的小程序的支持都很不错,所以Token成为了用于验证的极好选择。

3.在项目中引入JWT扩展

composer require firebase/php-jwt

4.JWT具体使用步骤

在登录控制器中

$key = 'e10adc3949ba59abbe56e057f20f883e';//自定义秘钥,加密解密都需要用到
$time = time(); //当前时间
$token = [
  'iat' => $time, //签发时间
  'nbf' => $time, //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
  'data' => [
    'userid' => 1,
    'username' => 'zqw.xyz',
  ]];
$jwtToken = \Firebase\JWT\JWT::encode($token, $key);

登录成功后,将生成 token 返回给前端。前端记录该用户信息的 token ,将 token 放入 head,之后的请求中都需要 head 都需包含 token。

我们可以定义一个 AppID 和 AppSecret,同时告知前端。前端每次请求中携带 AppID ,请求参数加入一个必要参数 sign ,sign 是由所有请求参数拼接而成加密后的加密串。
注意: sign 参数值,需要加入 AppID 所需要对应 AppSecret,请求参数和后端约定相同排序规则,然后进行加密。

后端验证签名是否通过

$token = $request->instance()->header('token');
if(empty($token)){
  abort(0, 'token验证失败');
}
$appid = $request->param('appid');
if(empty($appid)){
  abort(0, 'appid验证失败');
}
$request_time = $request->param('request_time');
if(empty($request_time)){
  abort(0,'时间戳验证失败');
}
$random_number = $request->param('random_number');
if(empty($random_number)){
  abort(0,'数字验证失败');
}
//记录每次请求的uuid,如果uuid已存在,则该次请求无效。

$request_uuid = Db::name('request')->where('uuid',$random_number)->find();
if(count($request_uuid) > 1){
  abort(0,'请求无效');
}else{
  Db::name('request')->insert([
    'uuid' => $random_number,
    'add_time' => time(),
    'url' => $request->baseUrl(),
  ]);
}



$secret_type = [
  'appid1' => 'bd98e16b5eaf3e49fa2ecd3f9ee8f6ae',
  'appid2' => 'b7e23061042f2799180e41d94cdbf861',
];
$secret = $secret_type[$appid];
if(empty($random_number)){
  abort(0,'secret验证失败');
}
$sign = $request->param('sign');
if(empty($sign)){
  abort(0,'sign验证失败');
}

$all_obj['secret'] = $secret;
ksort($all_obj);
$sign_key = '';
foreach ($all_obj as $k => $v) {
  $sign_key .= $k.='='.$v.'&';
}
$sign_key = substr_replace($sign_key ,"", -1);
$md_sign = md5($sign_key);
if($sign !== $md_sign){
  abort(0,'签名验证失败');
}
注意: 为防止重复请求,建议由前端每次传入 uuid ,根据 uuid 请求是否重复。
6.验证通过后,进行相关的业务逻辑代码处理。

// 
$result = array(
  'status' => 1,
  'msg' => '获取成功',
  'result' => array(
  )
);
return json($result)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
[转帖]PHP世纪万年历
Dec 06 PHP
PHP中array_map与array_column之间的关系分析
Aug 19 PHP
php之readdir函数用法实例
Nov 13 PHP
php提交post数组参数实例分析
Dec 17 PHP
PHP实现批量上传单个文件
Dec 29 PHP
Yii2实现让关联字段支持搜索功能的方法
Aug 10 PHP
PHP基于堆栈实现的高级计算器功能示例
Sep 15 PHP
实例分析PHP中PHPMailer发邮件
Dec 13 PHP
php中的explode()函数实例介绍
Jan 18 PHP
PHP中引用类型和值类型功能与用法示例
Feb 26 PHP
php学习笔记之字符串常见操作总结
Jul 16 PHP
Thinkphp5.0框架使用模型Model的获取器、修改器、软删除数据操作示例
Oct 11 PHP
PHP7创建销毁session的实例方法
Feb 03 #PHP
PHP7创建COOKIE和销毁COOKIE的实例方法
Feb 03 #PHP
Laravel + Elasticsearch 实现中文搜索的方法
Feb 02 #PHP
php封装的page分页类完整实例代码
Feb 01 #PHP
PHP实现简单的协程任务调度demo示例
Feb 01 #PHP
PHP设计模式之组合模式定义与应用示例
Feb 01 #PHP
php实现的简单多进程服务器类完整示例
Feb 01 #PHP
You might like
基于PHP中的常用函数回顾
2013/07/11 PHP
关于WordPress的SEO优化相关的一些PHP页面脚本技巧
2015/12/10 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
php 删除一维数组中某一个值元素的操作方法
2018/02/01 PHP
Laravel框架验证码类用法实例分析
2019/09/11 PHP
javascript事件问题
2009/09/05 Javascript
Javascript实现带关闭按钮的网页漂浮广告代码
2014/01/12 Javascript
jQuery打印指定区域Html页面并自动分页
2014/07/04 Javascript
jQuery.Highcharts.js绘制柱状图饼状图曲线图
2015/03/14 Javascript
详解vue 组件之间使用eventbus传值
2017/10/25 Javascript
解决vue2.0动态绑定图片src属性值初始化时报错的问题
2018/03/14 Javascript
详解vue中组件参数
2018/07/09 Javascript
JavaScript实现文件下载并重命名代码实例
2019/12/12 Javascript
element-ui中按需引入的实现
2019/12/25 Javascript
js校验开始时间和结束时间
2020/05/26 Javascript
vuex页面刷新导致数据丢失的解决方案
2020/12/10 Vue.js
Python中functools模块的常用函数解析
2016/06/30 Python
关于Python中异常(Exception)的汇总
2017/01/18 Python
python中requests小技巧
2017/05/10 Python
Python中的CSV文件使用"with"语句的方式详解
2018/10/16 Python
使用python批量修改文件名的方法(视频合并时)
2020/03/24 Python
python实现加密的方式总结
2020/01/19 Python
Python的collections模块真的很好用
2021/03/01 Python
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
关于canvas.toDataURL 在iOS运行失败的问题解决
2020/09/16 HTML / CSS
北京一家公司的.net开发工程师笔试题
2012/04/17 面试题
大学生入党思想汇报
2014/01/14 职场文书
办公室员工岗位工作职责
2014/03/10 职场文书
大学生求职信
2014/06/17 职场文书
水污染治理工程专业自荐信
2014/06/21 职场文书
四风问题个人对照检查材料
2014/09/26 职场文书
幼儿园教师考核评语
2014/12/31 职场文书
2016教师廉洁教育心得体会
2016/01/13 职场文书
超外差式晶体管收音机的组装与统调
2021/04/22 无线电
mysql分组后合并显示一个字段的多条数据方式
2022/01/22 MySQL
Mysql的Table doesn't exist问题及解决
2022/12/24 MySQL