
欢迎访问云轩博客
在这里可以看到前端技术,后端程序,网站内容管理系统等文章,还有我的程序人生!
欢迎来到
-----云轩博客
欢迎来到
-----云轩博客
欢迎来到
-----云轩博客
欢迎来到
-----云轩博客


TP5.1使用JWT进行TOKEN令牌生成与验证
共720人围观 0个不明物体
传统互联网项目在实现保持登录状态、退出登录、接口请求等功能时会使用Session,但是众所周知Session数据在产生后会存储与服务器端,所以当用户量达到一定程度会相应影响到服务器的性能,且Session在前后端分离的项目中或是多服务器项目中的支持不是很好。但是Token不会产生这些问题,服务器端对Token只有生成和验证操作,不会存放数据,针对前后端分离的项目,包括手机APP和当前热门的小程序的支持都很不错,所以Token成为了用于验证的极好选择。
jwt又是什么呢?
JWT全称为Json Web Token,是一种基于Token的身份认证方案,JWT的安全特性可以使Token不被修改和伪造。
接下来说一下怎么在tp5.1中使用jwt
首先需要使用Composer来为我们的TP5.1项目安装JWT。在TP5.1项目中使用命令行运行以下代码即可自动下载安装:
composer require firebase/php-jwt
运行后出现以下字样并在框架vendor下可以找到firebase即代表下载安装成功。
JWT成功集成到框架中后便可以使用了,这里再说明一下JWT生成的TOKEN格式。
首先我们可以进入JWT的官网,首页有一个Debugger可以用于查看生成与验证Token,除了官网我更推荐使用JWT的浏览器插件,不论哪种方法,最终使用效果都是一样的,我这里使用JWT插件来演示,首先打开Debugger就可以看到官方生成用于展示的Token:
可以清楚看到整个Token分为三个部分,每个部分之间有一个 . 作为隔断,首先红色的部分为头部(Header):说明此串码为JWT和加密所用的算法信息,紫色的部分为负载(Payload):用于添加想要传递的信息和Token基本设置等,最后蓝色的部分为验证签名(verify signature):用于密匙加密解密Token。知道了Token基本的格式后我们就可以开始使用TP5.1生成一个JWT看看效果了,为了方便演示,我将生成的函数放在了公共函数文件common.php中。
/** * 创建 token * @param array $data 必填 自定义参数数组 * @param integer $exp_time 必填 token过期时间 单位:秒 例子:7200=2小时 * @param string $scopes 选填 token标识,请求接口的token * @return string */ public function createToken($data = "", $exp_time = 0, $scopes = "") { //JWT标准规定的声明,但不是必须填写的; //iss: jwt签发者 //sub: jwt所面向的用户 //aud: 接收jwt的一方 //exp: jwt的过期时间,过期时间必须要大于签发时间 //nbf: 定义在什么时间之前,某个时间点后才能访问 //iat: jwt的签发时间 //jti: jwt的唯一身份标识,主要用来作为一次性token。 //公用信息 try { $key = 'TokenKey'; $time = time(); //当前时间 $token['iss'] = 'Jouzeyu'; //签发者 可选 $token['aud'] = ''; //接收该JWT的一方,可选 $token['iat'] = $time; //签发时间 $token['nbf'] = $time+3; //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用 if ($scopes) { $token['scopes'] = $scopes; //token标识,请求接口的token } if (!$exp_time) { $exp_time = 7200;//默认=2小时过期 } $token['exp'] = $time + $exp_time; //token过期时间,这里设置2个小时 if ($data) { $token['data'] = $data; //自定义参数 } $json = JWT::encode($token, $key); //Header("HTTP/1.1 201 Created"); //return json_encode($json); //返回给客户端token信息 return $json; //返回给客户端token信息 } catch (\\Firebase\\JWT\\ExpiredException $e) { //签名不正确 $returndata['code'] = "104";//101=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } catch (Exception $e) { //其他错误 $returndata['code'] = "199";//199=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } }
代码中使用JWT生成Token需要三个参数,分别是负载(Payload)、密匙(secret)、加密算法(algorithm),其中密匙是由自己规定的,之后接收到传来的Token时需要使用此密匙来验证接收到的Token,负载部分为想要传输的信息,其中有一些字段为官方定义的,但是并不是必需的,除此之外我们还可以定义一些自己的私有字段用来传输额外信息,例如以上实例中将签发时间和生效时间设置为当前时间,Token过期时间为当前时间的七天后,并加上了自己定义的管理员ID字段和是否是管理员的字段。
定义好这些信息后就可以使用JWT的静态方法encode来生成一个Token,生成的Token的格式:
string(225) "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzb2wiLCJleHAiOjE1NjU1OTYyNzYsImF1ZCI6ImFkbWluIiwibmJmIjoxNTY0OTkxNDc2LCJpYXQiOjE1NjQ5OTE0NzYsImFkbWluX2lkIjoiNjY2IiwiYWRtaW4iOnRydWV9.jCVh-13ZOBEiIORdmw9Ye191X9ZJNyjo4fN96umG878"
至此便成功的使用JWT生成可用的TOKEN了,那么接下来就需要在框架中对接收到的TOKEN进行验证了
同样在common.php中写入验证的函数:
/** * 验证token是否有效,默认验证exp,nbf,iat时间 * @param string $jwt 需要验证的token * @return string $msg 返回消息 */ public function checkToken($jwt) { $key = 'TokenKey'; try { JWT::$leeway = 60;//当前时间减去60,把时间留点余地 $decoded = JWT::decode($jwt, $key, ['HS256']); //HS256方式,这里要和签发的时候对应 $arr = (array)$decoded; $returndata['code'] = "200";//200=成功 $returndata['msg'] = "成功";// $returndata['data'] = $arr;//返回的数据 return json_encode($returndata); //返回信息 } catch (\\Firebase\\JWT\\SignatureInvalidException $e) { //签名不正确 //echo "2,"; //echo $e->getMessage(); $returndata['code'] = "101";//101=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } catch (\\Firebase\\JWT\\BeforeValidException $e) { // 签名在某个时间点之后才能用 //echo "3,"; //echo $e->getMessage(); $returndata['code'] = "102";//102=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } catch (\\Firebase\\JWT\\ExpiredException $e) { // token过期 //echo "4,"; //echo $e->getMessage(); $returndata['code'] = "103";//103=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } catch (Exception $e) { //其他错误 //echo "5,"; //echo $e->getMessage(); $returndata['code'] = "199";//199=签名不正确 $returndata['msg'] = $e->getMessage(); $returndata['data'] = "";//返回的数据 return json_encode($returndata); //返回信息 } //Firebase定义了多个 throw new,我们可以捕获多个catch来定义问题,catch加入自己的业务,比如token过期可以用当前Token刷新一个新Token }
验证Token需要的静态方法decode同样需要三个参数,第一个是需要验证的Token,第二个是验证的密匙,第三个是加密算法。
这里对异常捕捉没有具体细分,不论是密匙错误还是Token过期还是其他错误统统都是验证失败,如果想将异常信息获取的具体一点可以使用firebase中的三个异常信息来捕获,请自己测试。
验证token
//接口头部传来的Token$token = Request::header('token');//接受返回的结果$checkToken = action('checkToken', ['jwt' => $token]);
在具体业务中生成Token往往用于首次登录或者修改密码等信息后重登陆或者同账号异地登陆顶号操作,在用户进行操作时可以延长Token过期时间避免正在操作时突然提示Token过期重登陆破坏使用体验。后台生成Token和其他信息一起返回前端后需要将Token信息保存在本地存储或Cookie中,在下一次请求发送时将Token放在HTTP请求头中一起发送,后台在接收到后先验证Token是否正确可用在进行之后操作。
请求头添加Token只需在Ajax请求中添加以下字段即可:
headers:{ token:'HTTP HEADER AJAX TOKEN TEST'}
在后台获取只需使用Request静态方法单独获取头部token字段即可获取Token内容并进行后续的验证操作:
$token = Request::header('token');
—————————————————————————————————————
亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您们的支持是我的动力。
赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!

js获取dom元素的子元素,父元素,兄弟元素
共510人围观 0个不明物体
原生js:
var a = document.getElementById("dom");var b = a.childNodes; //获取a的全部子节点;var c = a.parentNode; //获取a的父节点;var d = a.nextSibling; //获取a的下一个兄弟节点var e = a.previousSibling; //获取a的上一个兄弟节点var f = a.firstChild; //获取a的第一个子节点var g = a.lastChild; //获取a的最后一个子节点
jq:
jQuery.parent(expr) //找父亲节点,可以传入expr进行过滤,比如$("span").parent()或者$("span").parent(".class") jQuery.parents(expr) //类似于jQuery.parents(expr),但是是查找所有祖先元素,不限于父元素 jQuery.children(expr) //返回所有子节点,这个方法只会返回直接的孩子节点,不会返回所有的子孙节点 jQuery.contents() //返回下面的所有内容,包括节点和文本。这个方法和children()的区别就在于,包括空白文本,也会被作为一个jQuery对象返回,children()则只会返回节点 jQuery.prev() //返回上一个兄弟节点,不是所有的兄弟节点 jQuery.prevAll() //返回所有之前的兄弟节点 jQuery.next() //返回下一个兄弟节点,不是所有的兄弟节点 jQuery.nextAll() //返回所有之后的兄弟节点 jQuery.siblings() //返回兄弟姐妹节点,不分前后 jQuery.find(expr) //跟jQuery.filter(expr)完全不一样。jQuery.filter()是从初始的jQuery对象集合中筛选出一部分,而jQuery.find()的返回结果,不会有初始集合中的内容,比如$("p"),find("span"),是从p元素开始找,等同于$("p span").
—————————————————————————————————————
亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您们的支持是我的动力。
赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!

IOS微信浏览器内H5页面点击事件失效
共454人围观 0个不明物体
在微信浏览器内的H5页面,当触发点击事件时有时会失效,点击没有效果,或者点击事件错位,其实这是因为在小屏幕上,在点击输入框弹出键盘 键盘回缩 后定位没有相应改变
也就是说,其实是input聚焦后页面被顶起,然后失焦后页面回位,但是这里只是视觉上回位了,window其实已经被顶上去一定的距离。你再次点击页面时就已经错位了,视觉上的点击事件触发按钮其实不是真正的按钮位置,所以点击时不会生效,而是在按钮上面一点距离点击它会生效(这要看被软键盘顶起多高了)。
解决办法:监听键盘触发事件,在监听到键盘关闭时将页面位置归零
keyboardEvents() { let myFunction; document.body.addEventListener('focusin', () => { // 软键盘弹起事件 clearTimeout(myFunction) }) document.body.addEventListener('focusout', () => { // 软键盘关闭事件 clearTimeout(myFunction) myFunction = setTimeout(function () { window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }) // =======当键盘收起的时候让页面回到原始位置 }, 200) }) }
—————————————————————————————————————
亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您们的支持是我的动力。
赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!

js radio更改checked属性的添加与移除
共614人围观 0个不明物体
今天碰到了一个问题,单选框在使用removeAttr()移除了单选框的checked属性后,使用attr()重新增加不起作用,解决办法如下:
$("input:radio").removeAttr('checked');//移除checked属性$("input:radio").prop('checked','true');//增加checked属性
移除checked属性还可以使用
$("input:radio").prop('checked','false');
对于HTML元素本身就带有的固有属性,在处理时,使用prop方法。
对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法。
如果通过prop()函数更改《input》和《button》元素的type属性,在多数浏览器上将会抛出一个错误,因为该属性一般不允许在后期更改。
如果使用prop()
函数操作表单元素的checked、selected、disabled等属性,如果该元素被选中(或禁用),则返回true
,否则(意即HTML中没有该属性)返回false
。
—————————————————————————————————————
亲爱的用户,您好!如果您喜欢这个网站,欢迎赞助我,您们的支持是我的动力。
赞赏款用于服务器、文章等网站的固定支出。欢迎大家支持,谢谢!