最近在折腾多端登录,面临的场景有 hybirdApp 有小程序 还有 web,目前采用的是通过定一个公共参数 token 来处理数据一致性保持会话一致性。
研究 JWT 的原因
目的达到了,但是 token 未做验证机制,无法确定用户情况,只要有人拿到这个 token 就可以长期使用。
目前遇到了因为 session 的一个错误使用将内容清空了的情况,导致 APP 端重复要求登录,登录后仍然要求登录的现状,虽最终将有问题的 session 清空操作给屏蔽掉,但并没有从根本上解决问题
JWT 就是一个字符串,经过加密处理与校验处理的字符串,由三个部分组成。基于 token 的身份验证可以替代传统的 cookie+session 身份验证方法。三个部分以.分割:header.payload.signature 参见 php JWT 在 web 端的使用方法
JWT 的特点
无 session 无 cookies。 可以自称体系,不局限于一个钟新服务器
为了迁移到微服务架构,由于服务分拆之后,单一的登录入口点消失了,采用 Token 是必然之选。
为了伸缩性考虑,采用 Cookie + Session 机制,必然面临着应用状态的问题,而且必然牵涉到 session 的复制。采用 Token,天然避免这一点。这里并非是指完全无 Session 化,但起码可以降至最少。
为了移动端考虑,Token 更适合移动端,比 Cookie 更灵活了。
为了安全性考虑,Token 机制【仅验证 request header 时】天然对 CSRF 免疫。
JWT 在 PHP 中的应用
目前有多个 php 的类库或者扩展在使用中达到了 jwt.io 的要求。我这里比较推荐的有两个非扩展类库 firebase/php-jwt 和 lcobucci/jwt 第二个比第一个功能更全一些
JWT 在使用中的注意事项
使用了 JWT 我们一般都会考虑两点:
1. 签名是否正确?
2. Token是否到期?
这两块可以通过校验几个字段来处理
1. 建立 token 吊销机制,将 token 写入数据库,
2. 无效 token 因未入数据库,所以确信传入的 token 是有效的。
3. 对有效的 token 进行签名验证,获取到 token 后重新生成签名进行校验 token 的签名部分( C 位的值)是否一致。
4. 确认是否 token 超时可以通过 exp(expire 指定token的生命周期。unix时间戳格式) 和 nbf(not before。如果当前时间在nbf里的时间之前,则Token不被接受。unix时间戳格式。) 声明,获取到 token 后,对时间进行判断。
5. 为了防止replay attack,可加上 iss(issuer 请求实体,可以是发起请求的用户的信息,也可是jwt的签发者。),jti (JWT ID。针对当前token的唯一标识) 和 iat(issued at。 token创建时间,unix时间戳格式) 声明,然后获取到 token 后,对声明信息进行匹配。
复制代码
通过以上可以看到我们在使用 JWT 时需要创建一个数据库存储 token ;并生成 token 的 jti(JWT ID。针对当前 token 的唯一标识)