JWT简单介绍
这里是修真院后端小课堂,每篇分享文从 【背景介绍】【知识剖析】【常见问题】【解决方案】【编码实战】【扩展思考】【更多讨论】【参考文献】 八个方面深度解析后端知识/技能,本篇分享的是: 【JWT简单介绍。】 大家好,我是IT修真院郑州分院第11期的学员何爽,一枚正直纯洁善良的后端程序员,今天给大家分享一下,修真院官网java(职业)任务5,深度思考中的知识点——JWT简单介绍。 1.背景介绍 由于微服务大都是分布式的,需要几台服务器部署,当一个用户在其中一台服务器登录后,传统的方式是session保存其登录信息,然后可以使用共享存储共享,比如redis共享,这种方案的缺点在于共享存储需要一定保护机制,因此需要通过安全链接来访问,这时解决方案的实现就通常具有相当高的复杂性了,所以这里使用基于令牌的方式做登录。 什么是JWT? JWT(JSON WEB TOKEN):JSON网络令牌,JWT是一个轻便的安全跨平台传输格式,定义了一个紧凑的自包含的方式在不同实体之间安全传输信息(JSON格式)。 它是在Web环境下两个实体之间传输数据的一项标准。实际上传输的就是一个字符串。 广义上讲JWT是一个标准的名称;狭义上JWT指的就是用来传递的那个token字符串 2.知识剖析 JWT的结构: JWT包含了使用.分隔的三部分:?Header?头部?Payload?负载?Signature?签名 其结构看起来是这样的Header.Payload.Signature JWT?的?header?中承载了两部分信息 { ? "alg": "RS256", ? "typ": "JWT" } alg:?声明加密的算法 typ:?声明类型 对这个头部信息进行?base64,即可得到?header?部分 payload?是主体部分,意为载体,承载着有效的?JWT?数据包,它包含三个部分 标准声明 公共声明 私有声明 标准声明的字段 interface Stantar { ? iss?: string; // JWT的签发者 ? sub?: string; // JWT所面向的用户 ? aud?: string; //?接收JWT的一方 ? exp?: number; // JWT的过期时间 ? nbf?: number; //?在xxx日期之间,该JWT都是可用的 ? iat?: number; //?该JWT签发的时间 ? jti?: number; //JWT的唯一身份标识 } ?公共声明的字段 interface Public { ? [key: string]: any; } 公共声明字段可以添加任意信息,但是因为可以被解密出来,所以不要存放敏感信息。 私有声明的字段 interface Private { ? [key: string]: any; } 私有声明是?JWT?提供者添加的字段,一样可以被解密,所以也不能存放敏感信息。 signature(签名) 把header和payload对应的json结构进行base64url编码之后得到的字符串用点号拼接起来,然后根据header里面alg指定的签名算法生成出来的,然后添加自己设定的key进行加密签名。 JWT设计单点登录系统过程: 用户认证八步走 所谓用户认证(Authentication),就是让用户登录,并且在接下来的一段时间内让用户访问网站时可以使用其账户,而不需要再次登录的机制。 首先,服务器应用(下面简称“应用”)让用户通过Web表单将自己的用户名和密码发送到服务器的接口。这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。 接下来,应用和数据库核对用户名和密码。 核对用户名和密码成功后,应用将用户的id(图中的user_id)作为JWT Payload的一个属性,将其与头部分别进行Base64编码拼接后签名,形成一个JWT。这里的JWT就是一个形同lll.zzz.xxx的字符串。 应用将JWT字符串作为该请求Cookie的一部分返回给用户。注意,在这里必须使用HttpOnly属性来防止Cookie被JavaScript读取,从而避免跨站脚本攻击(XSS攻击)。 在Cookie失效或者被删除前,用户每次访问应用,应用都会接受到含有jwt的Cookie。从而应用就可以将JWT从请求中提取出来。 应用通过一系列任务检查JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。 应用在确认JWT有效之后,JWT进行Base64解码(可能在上一步中已经完成),然后在Payload中读取用户的id值,也就是user_id属性。这里用户的id为1025。 应用从数据库取到id为1025的用户的信息,加载到内存中,进行ORM之类的一系列底层逻辑初始化。 应用根据用户请求进行响应。 3.常见问题 为什么使用JWT 4.解决方案 (1)前后端分离 以前的传统模式下,后台对应的客户端就是浏览器,就可以使用session+cookies的方式实现登录,但是在前后分离的情况下,后端只负责通过暴露的RestApi提供数据,而页面的渲染、路由都由前端完成。因为rest是无状态的,因此也就不会有session记录到服务器端。 (2)传统方式带来的安全性问题 (3)性能问题 如果将验证信息保存在数据库中,后端每次都需要根据token查出用户id,这就增加了数据库的查询和存储开销 5.编码实战 6.扩展思考 为什么不推荐用JWT做单点登录我这里却做了单点登录的介绍? 通常因为续签问题导致我们不推荐使用JWT做单点登录,但续签问题可以通过以下的方案进行解决: 每次请求刷新?jwt 只要快要过期的时候刷新jwt 完善?refreshToken 使用?redis?记录独立的过期时间 用JWT做单点登录的优点: Session方式来存储用户id,一开始用户的Session只会存储在一台服务器上。对于有多个子域名的站点,每个子域名至少会对应一台不同的服务器,例如: www.taobao.com,nz.taobao.com,login.taobao.com 所以如果要实现在login.taobao.com登录后,在其他的子域名下依然可以取到Session,这要求我们在多台服务器上同步Session 使用JWT的方式则没有这个问题的存在,因为用户的状态已经被传送到了客户端。因此,我们只需要将含有JWT的Cookie的domain设置为顶级域名即可,例如 Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000; domain=.taobao.com 注意domain必须设置为一个点加顶级域名,即 .taobao.com。这样,taobao.com和*.taobao.com就都可以接受到这个Cookie,并获取JWT了. 7.参考文献 https://blog.csdn.net/congyihao/article/details/70197805 https://blog.csdn.net/achenyuan/article/details/80829401 https://blog.csdn.net/qq_39691226/article/details/80570941 8.更多讨论 Q1:提问人:周宏浩: ?JWT?Token需要持久化在Memcached中吗?? A1:回答人(何爽): ?这个看业务需求,如果需要长期保存用户的信息那就要持久化,如果只是短时间甚至一次性的用户信息验证那就不需要做持久化。? Q2:提问人:张亚强 ?感觉jwt的加密只是又增加了des的加密,造成了双重加密,而不是改变了jwt头部的base64加密吧 A2:回答人(何爽): ?这个确实是改变了头部的加密方式,将头部的base64加密换成了des加密方式,因为des加密在当前是一种几乎不可能被破解的加密方式。 Q3:提问人:周宏浩 ?服务器端是否应该从JWT中取出userid用于业务查询? A3:回答人(何爽): ?需要,我们利用JWT的时候就将userid放进了jwt的头部,因此当我们需要用到userid的时候就取出来用于业务的需求。 9.鸣谢 感谢张强,翁涵师兄,此教程是在他们之前技术分享的基础上完善而成。 10.结束语 今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~ PPT链接?视频链接 更多内容,可以加入IT交流群565734203与大家一起讨论交流 这里是技能树·IT修真院:,初学者转行到互联网的聚集地 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |