传统的web端登录,是将登录信息缓存到服务端的session中,每个session有一个唯一的sessionId。浏览器请求服务端会自动在请求头的cookie中带上sessionId,一般开发的时候对sessionId是无感知的。而token的本质是一段加密的字符串,包含了登录用户的信息
token登录验证序列图
token登录序列图.png
为什么使用token
相比session而言,token有以下几点优势
- 服务端不需要缓存用户信息,减少服务器压力
- token缓存在客户端,服务器重启,登录状态不会失效
- session是浏览器特有的,app要支持会比较繁琐,token就没有这样的限制
- 易于扩展,存在多台服务器的情况下,使用负载均衡,第一次登录请求转发到A服务器,在A服务器的session中缓存了用户的登录信息,如果第二次请求转发到了B服务器,就丢失了登录状态。虽然可以使用redis等手段共享session,但token就简单很多,不同的服务器只需要使用相同的一段解密代码即可
java生成token方法
JWT(JSON Web Token)
网上找到的大部分资料都是使用JWT来生成token,JWT生成的token包含三部分
- header:包含token类型和加密算法
- payload:存放自定义数据
- signature:对前面两部分的签名,防止篡改数据\r\n\r\n用JWT生成的token是很长的一串字符串,用Base64进行编码,可以解码出原数据,注意不能放一些私密信息,比如用户密码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\r\n.eyJleHBpcmVUaW1lIjoxNTQ5NTU0NDUyLCJ1c2VyTmFtZSI6IuacveacqCIsInVzZXJJZCI6IjY2NiJ9\r\n.fiQKWuMTWbkfQ3dOozoJr13pJSmKnc5El4EBnKyU42o
上面这很长的一串就是用JWT生成的token,可以感受一下这个长度。客户端的每次请求都要带上这么一大串,服务端的每次响应都要返回这么一大串,我个人是难以接受的。所以我用了下面那种方法
AES(Advanced Encryption Standard)
token本质是一段加密的字符串,包含登录用户的一些信息,通过解密可以获取这些信息,所以理论上任何安全的加密解密手段都可以用来生成token
高级加密标准AES,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。AES采用对称加密,相比于非对称加密,对称加密效率更快
- 对称加密:加密和解密使用相同的密钥。适用于单方面的加密解密,密钥不能泄露
- 非对称加密:使用公钥加密,私钥解密。适用于一方加密,另一方解密,比如前后端的数据传输,可以在客户端使用公钥对数据进行加密,在服务端使用密钥进行解密,增强数据安全性
- token的加密解密都在服务端进行,所以使用对称加密的AES算法即可
EmaZUvyM9aabQ2Jmo6THJ/r3/e2xAjpRmoA5TzvuR4I=
上面这一小串就是用AES生成的token了,是不是清爽了很多,而且没有密钥无法解密,相比JWT生成的token,AES生成的token携带的数据更安全
作者:朽木_a25b
链接:https://www.jianshu.com/p/7c34b78f1675