聊一聊数据接口的登录态校验以及JWT


声明:本文转载自https://my.oschina.net/piscdong/blog/3136669,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

最近和群里网友聊天,发现他在数据接口中校验登录状态用的还是session,在我及时劝说和科普之后,他最终决定改用JWT。那么接下来我们就聊一聊数据接口应该怎么管理登录状态以及什么是JWT

混合开发的时候是怎么做的

前后端混合开发的时候,用户登录状态的管理一般都是通过session来实现的,原理很简单:用户登录后,服务端将登录用户信息存储到服务器上的特定位置,并生成对应的session id存储到浏览器的cookie中。需要校验的时候先读取cookie中的session id,找到服务器中对应的存储内容,完成校验。

很显然,这个机制是建立在cookie基础上的,cookie又依赖于浏览器,而且有域名限制。是不适合app、小程序、以及前后端时数据接口采用其他域名等情况的。

app、小程序、前后端分离的时候要怎么做

app、小程序、前后端分离时的数据接口一般采用token来做登录信息校验。原理是用户登录后,服务端生成对应用户的一个token(一般都是一段无意义的唯一字符串)后返回,app、小程序、前端(以下统称为前端)拿到token后保存,在需要校验用户登录的接口请求中加入token(可以是get、post参数或者http header的形式),服务端拿到token后校验真实性、有效性等信息后完成登录校验。一般为了防止盗用,还会设置一套签名校验的过程。

其实token和session的原理是差不多的,都是服务端将对应用户的一个key(session的时候是session id,token的时候就是token)交给前端,前端通过token请求服务端,服务端再去反查用户,获取用户登录状态。

现在一般微信、微博等接口都是采用的这种方式。但是这种方式也有弊端,主要是:

  1. 服务端必须保存token,以及有效期,校验的时候必须要有数据读取的过程;
  2. 校验签名的时候一般需要一个secret做为加密签名的附加字符,前端必须也要同时保存这个secret,这样显然不适合代码会暴露的网页前端。

这时候,就轮到我们这次的主角JWT出场了。

什么是JWT

JWT是JSON Web Token的简称,有官网详细介绍,大家可以看一看,这里简单说一下。

JWT其实就是一种特殊的token,原理和使用方法自然和token一样。

JWT是由三部分组成的字符串,结构是:头部+主体内容(官方称之为Payload)+签名,三部分用“.”连接。头部和主体内容都是json格式的字符串再经过base64编码,为了方便放在get请求中,还需要把类似“=”、“/”等特殊字符替换掉。

头部内容是固定的,原始json就是下面这样

{
	"alg": "HS256",
	"typ": "JWT"
}

主要是说明了最后签名部分的加密算法。

重点是中间的主体内容,原始json一般是类似下面这样的

{
	"user": "John Doe",
	"exp": "2020-01-01 12:24:30"
}

主体内容一个是当前登录的用户,可以是用户id,也可以是用户名等可以检索定位到用户的信息;还有一个就是过期时间。还可以加入一些其他不私密的信息。

服务端拿到JWT之后可以在不读取数据的情况下,仅通过解码这部分信息就可以完成获取登录用户以及判断是否过期等初期工作。

最后的签名一般是把头部、主体内容再加上secret拼接成字符串再加密,这一步在用户登录生成JWT的时候就完成了。服务端拿到JWT之后只需要把前两部分加上secret再计算一次签名加以比对就可以完成校验签名,前端不需要同时保存secret。

JWT官网提供了各种服务端语言的生成代码,这里我提供一个我自己用PHP写的相对简化的方法,供大家参考

private function _jwt($payload){
	$header['alg']='HS256';
	$header['typ']='JWT';
	$jwt_header=$this->_base64url($header);
	$jwt_payload=$this->_base64url($payload);
	$jwt_sign=hash_hmac('sha256', $jwt_header.'.'.$jwt_payload, $this->secret);
	$jwt['token']=$jwt_header.'.'.$jwt_payload.'.'.$jwt_sign;
	$jwt['sign']=$jwt_sign;
	return $jwt;
}

private function _base64url($a){
	$c=base64_encode(json_encode($a));
	$c=str_replace('=', '', $c);
	$c=str_replace('+', '-', $c);
	$c=str_replace('/', '_', $c);
	return $c;
}

我这个方法里需要把主题内容以数组形式的参数传入,最终返回了生成的JWT和签名,方便接收时校验签名。

最后再说一下缺点

JWT在实际使用中也是存在问题的,目前想到以下几点:

  1. 安全性:签名包含在token中,一旦token整体被盗用,将没有办法区分,所以有网友称之为“裸奔”;
  2. 过期时间放在token中而不是服务端保存处理,一旦token生成并签发出去,将无法灵活的控制有效期;
  3. 最后一个是用户体验,其实可以算是token方式的通病。这个问题我也和群友讨论过,大家在访问部分社区的时候应该会遇到过,还在访问过程中突然变成未登录。我觉得这主要时因为服务端在token过期后就即时判断为用户登录失败,不管你在网页上处于什么状态。这个问题在session方式中是不存在的,前面说过session依赖于cookie,而存储session id的cookie是会保存在整个浏览器进程,就是说只要浏览器不关闭,用户就可以一直保持登录状态。

本文发表于2019年12月03日 11:00
(c)注:本文转载自https://my.oschina.net/piscdong/blog/3136669,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 104 讨论 0 喜欢 0

讨论

周娱

君子和而不同
按照自己的方式,去度过人生

8027 3840157
抢先体验

扫码体验
趣味小程序
文字表情生成器

加入组织

扫码添加周娱微信
备注“加入组织”
邀请进开发群

闪念胶囊

人活一辈子,不是一年两年。时间是有连续性的,做抉择的时候要多看几步。保持警惕,大丈夫有所为,有所不为。

跟人接触,不要想:我能从你身上得到什么,要想:我能给你什么。 想通了,内核就稳了。

这个世界上,别人只会看你现在的样子而不是以后的样子。你以后的样子只有自己才相信。如果没有执行力,一切都是虚妄。

对普通人来说,人和人相处其实最重要的是感觉。感觉不好,你说什么都没用,怎么解释都没用,越说越错,反正最后不好的锅都往你身上扣。所谓“说你行你就行,不行也行。说你不行,你就不行,行也不行”就是这个意思。狼要吃人根本不需要理由,你也同样叫不醒装睡的人。遇到这种情况,早点闪人才是上策。不过大部分人的问题是没有闪人的心态,能力,和资源。

考985不牛逼,考上才牛逼。创业不牛逼,创业成功才牛逼。这个社会上很多人把目标当成牛逼的资本,牛逼哄哄的,死活不听劝,然后做的一塌糊涂,给别人添麻烦,让别人帮他料理后事,对此只能呵呵。

当你尝到用生气解决问题的甜头后,你就懒得再用其他方式了。你却忽略了,生气是鸩毒啊,剂量用够了,你的关系也玩完了。

年轻的时候你只搞事业不谈恋爱,等你事业有成了,钱相对自由了,你可能已经没有荷尔蒙了。

如果你经常雇佣比你矮小的人,将来我们就会变成矮人国,变成一家侏儒公司。相反,如果你每次都雇用比你高大的人,日后我们必能成为一家巨人公司。

如果一个人有充裕的时间去完成一项工作,那么他就会放慢节奏或者增加其他不必要的工作,直到花光所有的时间。

Copyright © 2016 - 2020 Cion.
All Rights Reserved.
备案:鲁ICP备19012333号-4.