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函数(简单整理)
Apr 30 PHP
php empty()与isset()区别的详细介绍
Jun 17 PHP
ThinkPHP模板判断输出Defined标签用法详解
Jun 30 PHP
Laravel 4 初级教程之视图、命名空间、路由
Oct 30 PHP
ThinkPHP水印功能实现修复PNG透明水印并增加JPEG图片质量可调整
Nov 05 PHP
PHP中使用socket方式GET、POST数据实例
Apr 02 PHP
php隐藏实际地址的文件下载方法
Apr 18 PHP
深入浅出php socket编程
May 13 PHP
学习php设计模式 php实现装饰器模式(decorator)
Dec 07 PHP
PHP几个实用自定义函数小结
Jan 25 PHP
PHP简单实现无限级分类的方法
May 13 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
Feb 21 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安全配置
2006/12/06 PHP
PHP反射使用实例和PHP反射API的中文说明
2014/07/02 PHP
php超快高效率统计大文件行数
2015/07/05 PHP
一个非常实用的php文件上传类
2017/07/04 PHP
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
仅img元素创建后不添加到文档中会执行onload事件的解决方法
2011/07/31 Javascript
document.createElement()用法及注意事项(ff下不兼容)
2013/03/13 Javascript
js substr支持中文截取函数代码(中文是双字节)
2013/04/17 Javascript
js控制frameSet示例
2013/09/10 Javascript
javascript模拟枚举的简单实例
2014/03/06 Javascript
javasciprt下jquery函数$.post执行无响应的解决方法
2014/03/13 Javascript
javascript父、子页面交互技巧总结
2014/08/08 Javascript
javascript实现动态模态绑定grid过程代码
2014/09/22 Javascript
angularjs表格分页功能详解
2016/01/21 Javascript
关于JS中的方法是否加括号的问题
2016/07/27 Javascript
全面解析jQuery中的$(window)与$(document)的用法区别
2017/08/15 jQuery
js 提取某()特殊字符串长度的实例
2017/12/06 Javascript
jQuery中图片展示插件highslide.js的简单dom
2018/04/22 jQuery
vue底部加载更多的实例代码
2018/06/29 Javascript
解决js相同的正则多次调用test()返回的值却不同的问题
2018/10/10 Javascript
webpack4手动搭建Vue开发环境实现todoList项目的方法
2019/05/16 Javascript
layui自定义工具栏的方法
2019/09/19 Javascript
JS实现滑动导航效果
2020/01/14 Javascript
js重写alert事件(避免alert弹框标题出现网址)
2020/12/04 Javascript
Python 使用SMTP发送邮件的代码小结
2016/09/21 Python
如何用Python合并lmdb文件
2018/07/02 Python
Python高级特性切片(Slice)操作详解
2018/09/27 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
2020/01/14 Python
python opencv实现直线检测并测出倾斜角度(附源码+注释)
2020/12/31 Python
应聘美工求职信
2013/11/07 职场文书
入党自我评价范文
2014/02/02 职场文书
销售合作意向书范本
2015/05/08 职场文书
婚宴致辞
2015/07/28 职场文书
保护环境建议书作文400字
2015/09/14 职场文书
Golang实现AES对称加密的过程详解
2021/05/20 Golang
vue3.0 数字翻牌组件的使用方法详解
2022/04/20 Vue.js