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+Html+缓存
Dec 20 PHP
php下实现在指定目录搜索指定类型文件的函数
Oct 03 PHP
php 文章采集正则代码
Dec 28 PHP
php 连接mssql数据库 初学php笔记
Mar 01 PHP
PHP输出数组中重名的元素的几种处理方法
Sep 05 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
May 06 PHP
PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解
Jun 25 PHP
解析php下载远程图片函数 可伪造来路
Jun 25 PHP
php设计模式之单例、多例设计模式的应用分析
Jun 30 PHP
php session_start()出错原因分析及解决方法
Oct 28 PHP
PHP版本升级到7.x后wordpress的一些修改及wordpress技巧
Dec 25 PHP
php 如何获取文件的后缀名
Jun 05 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
在“咖啡之国”感受咖啡文化
2021/03/03 咖啡文化
thinkPHP下的widget扩展用法实例分析
2015/12/26 PHP
PHP基于session.upload_progress 实现文件上传进度显示功能详解
2019/08/09 PHP
基于Laravel-admin 后台的自定义页面用法详解
2019/09/30 PHP
jQuery 1.5.1 发布,全面支持IE9 修复大量bug
2011/02/26 Javascript
jWiard 基于JQuery的强大的向导控件介绍
2011/10/28 Javascript
JavaScript设置IFrame高度自适应(兼容各主流浏览器)
2013/06/05 Javascript
判定是否原生方法的JS代码
2013/11/12 Javascript
js获取url参数代码实例分享(JS操作URL)
2013/12/13 Javascript
JavaScript通过正则表达式实现表单验证电话号码
2014/03/07 Javascript
jquery新的绑定事件机制on方法的使用方法
2014/04/15 Javascript
js变形金刚文字特效代码分享
2015/08/20 Javascript
jquery validate.js表单验证入门实例(附源码)
2015/11/10 Javascript
Jquery Easyui菜单组件Menu使用详解(15)
2016/12/18 Javascript
微信小程序 弹幕功能简单实例
2017/02/14 Javascript
微信小程序商城项目之侧栏分类效果(1)
2017/04/17 Javascript
微信小程序 判断手机号的实现代码
2017/04/19 Javascript
初探JavaScript 面向对象(推荐)
2017/09/03 Javascript
Node 升级到最新稳定版的方法分享
2018/05/17 Javascript
如何使用vuex实现兄弟组件通信
2018/11/02 Javascript
解决Vue+Electron下Vuex的Dispatch没有效果问题
2019/05/20 Javascript
js 递归json树实现根据子id查父id的方法分析
2019/11/08 Javascript
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
Selenium元素的常用操作方法分析
2018/08/10 Python
python sqlite的Row对象操作示例
2019/09/11 Python
html5 Canvas画图教程(7)—canvas里画曲线之quadraticCurveTo方法
2013/01/09 HTML / CSS
AmazeUI 点击元素显示全屏的实现
2020/08/25 HTML / CSS
英国最大的独立家具零售商:Furniture Village
2016/09/06 全球购物
俄罗斯香水和化妆品购物网站:Л’Этуаль
2018/05/10 全球购物
美国亚马逊旗下男装网站:East Dane(支持中文)
2019/09/25 全球购物
Eton丹麦官网:精美的男式衬衫
2020/05/27 全球购物
自我评价的正确写法
2013/09/19 职场文书
素食餐饮项目创业计划书
2014/02/02 职场文书
高中毕业典礼演讲稿
2014/09/09 职场文书
2014年教师节座谈会发言稿
2014/09/10 职场文书
学校领导干部民主生活会整改方案
2014/09/29 职场文书