客户端读取并返回JWT
var jwt = null; // 模拟用户登录获取JWT function doLogin() { var url = "http://localhost:8080/jwt/login"; var params = {"username": "zhangsan", "password": "111111"}; $.ajax({ type: "POST", url: url, dataType: "json", contentType: "application/json", data: JSON.stringify(params), success: function (data) { console.log(data.data); jwt = data.data; } }); } // 模拟用户登录之后执行操作,将JWT返回给服务端 function doList() { var url = "http://localhost:8080/jwt/list"; $.ajax({ type: "GET", url: url, headers: { // 客户端需要在HTTP请求消息头中将JWT返回给服务端 \'Authorization\': \'Bearer \' + jwt, }, success: function(data){ console.log(data); } }); } 总结 JWT运行流程 与传统Session方式的比较本质上来讲,JWT就是一种在网络应用中保存用户信息的方式。因此,不得不与传统的Session保存用户信息的方式进行比较。
基于Session方式保存用户信息
HTTP协议本身是无状态的,为了在Web应用中记住登录用户的信息,传统方式通过Session在服务端保存登录用户信息。具体实现为:用户访问网站时会在服务端随机生成一个Session ID,服务端使用该Session ID在内存中保存一个与之相关联的对象,再以Cookie的形式将该Session ID返回给浏览器客户端,以后每次浏览器客户端访问服务器时都以Cookie的形式将该Sesion ID再返回给服务器端,这是前提。在用户登录成功后,将相关信息保存在与该Session ID相关的对象中(通常是保存在内存),通过这种方式就实现了在服务器端保存用户信息。这种通过Cookie方式实现Session并在服务端保存用户信息的方式存在一些弊端:
(1)服务端内存压力大:Session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
(2)服务端扩展性不好:用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力,也意味着限制了应用的扩展能力。
(3)CSRF:因为是基于Cookie来实现Session的, 如果实现不当Cookie被截获,用户就会很容易受到跨站请求伪造的攻击。
基于Token方式保存用户信息
将用户信息基于Token方式在每次请求中进行传递,这样就不需要在服务端保存,大大降低了服务端的存储压力。另外,服务端可以实现任意的分布式扩容缩容。当然,基于Token方式保存用户信息的方式完全可以自定义实现(参考:细说REST API安全之访问授权),此时需要考虑如何保证Token安全传递等方方面面的因素。而基于JWT这样的标准结构,大大降低了实现的难度。
(1)由于JSON的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,PHP等很多语言都可以使用。
(2)因为有了Payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
(3)便于传输,JWT的构成非常简单,字节占用很小,所以它是非常便于传输的。
不应该在JWT的Payload部分存放敏感信息,因为Base64编码是很容易被解码的,这部分相当于明文数据。
保护好服务端用于加密的secret私钥,该私钥非常重要。
请使用https协议保证传输的安全性。
【参考】
[1]. https://www.jianshu.com/p/576dbf44b2ae 什么是 JWT -- JSON WEB TOKEN
[2]. https://blog.leapoahead.com/2015/09/06/understanding-jwt/ JSON Web Token - 在Web应用间安全地传递信息
[3]. 八幅漫画理解使用JSON Web Token设计单点登录系统