目录
1.cookie和session
1.1 实现
当用户登录成功之后, 我们把用户的信息保存到Session中,然后把该SessionId 以Cookie的形式保存到客户端浏览器上, 此后,该用户的所有请求都会把包含SessionId的Cookie带回给服务器, 服务器获取到SessionId, 通过改SessionId得到对应的Session对象, 这样就能获取到该用户登录时存到的信息了。
1.2 使用session存在的问题
(1)每次用户认证通过之后,服务器都需要创建一个Session对象来保存用户的信息,而Session是保存在内存中的,随着认证通过的用户越来越多,服务器保存的session也越来越多,服务器的内存开销也会越来越大;
(2)因为SessionId是基于Cookie来存储的, 如果Cookie被截获,用户就会很容易受到跨站请求伪造的攻击(CSRF攻击);
(3)当我们想要扩展我们的应用,让我们的数据被多个移动设备使用时,我们必须考虑跨资源共享问题。当使用AJAX调用从另一个域名下获取资源时,我们可能会遇到禁止请求的问题(CORS);
(4)在分布式集群系统中, 因为我们的后端应用是多节点部署的,而Session是存储在节点服务器上,这个时候,我们就需要实现Session的共享机制(使用Redis/memcache等缓存技术来存储session).不方便集群应用。
2.JWT
2.1 定义
JWT就是通过json格式作为Web应用程序中的令牌,用于在各方之间安全地将信息以JSON的形式传输,在数据传输过程中.还可以对数据进行加密,签名等相关处理。
2.2 实现
(1)前端通过web表单将自己的用户名和密码发送给后端的接口,这一过程一般就是一个HTTP POST请求.在实际开发中,我们可以通过SSL加密的传输(Https协议),从而避免敏感信息被嗅探;
(2)后端核对用户名和密码成功之后,将用户的id等其他信息作为JWT的payload(负载),将其与头部分别进行base64编码拼接之后签名,形成一个JWT(token).形成的JWT就是一个形同:aaa.bbb.ccc的字符串;
(3)后端服务将JWT字符串作为登录成功的返回结果返回给前端,前端可以将返回的结果保存在LocalStore或sessionStore上,退出登录时,前端删除保存的JWT即可;
(4)前端在每次请求时,将JWT放入HTTP的请求头中的Authorization中(解决XSS和XSRF问题);
(5)后端验证JWT的有效性,例如:检查签名是否正确,检查Token是否过期,检查Token的接收方是否是自己的(可选);
(6)验证通过后,后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应的结果;
(7)如果验证不通过, 响应错误信息给用户。
2.3 JWT结构
JSON Web令牌以紧凑的形式由三部分组成,这些部分由点(.)分隔,分别是头部(header)、载荷 (payload)、签名(signature),例:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
(1)头部
头部通常由两部分组成:令牌的类型(即JWT)和正在使用的签名算法(如:HMAC SHA256 或RSA),然后用Base64Url编码(该加密是可以对称解密的)得到头部。
(2)载荷
载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,载荷中放置了 token
的一些基本信息,以帮助接受它的服务器来理解这个 token
。同时还可以包含一些自定义的信息,用户信息交换。这些有效信息包含三个部分,分别为标准中注册声明、公共的声明和私有的声明。
①标准中注册声明(建议不强制使用)
{
"sub": "1",
"iss": "http://localhost:8000/auth/login",
"iat": 1451888119,
"exp": 1454516119,
"nbf": 1451888119,
"jti": "37c107e4609ddbcc9c096ea5ee76c667",
"aud": "dev"
}
②公共的声明
在使用 JWT 时可以额外定义的载荷。为了避免冲突,应该使用 IANA JSON Web Token Registry 中定义好的,或者给额外载荷加上类似命名空间的唯一标识。公共的声明可以添加任何的信息,一般添加用户的相关信息或其它业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密。
③私有的声明
在信息交互的双方之间约定好的,既不是预定义载荷也不是公有载荷的一类载荷。这一类载荷可能会发生冲突,所以应该谨慎使用。
(3)签名
签名时需要用到前面编码过的两个字符串,如果以 头部中指定的加密算法(HMACSHA256
) 加密,加密后再进行 base64url
编码最后得到的字符串就是 token
的第三部分,然后把这三部分使用拼接在一起,就得到一个完整的JWT了。签名的作用: 保证 JWT 没有被篡改过。
2.4 JWT的作用(优点)
(1)因为json的通用性,所以JWT是可以跨语言支持的,像C#,JavaScript,NodeJS,PHP等许多语言都可以使用;
(2)因为有了payload部分,所以JWT可以在自身存储一些其它业务逻辑所必要的非敏感信息;
(3)便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的;
(4)它不需要在服务端保存会话信息,所以它易于应用的扩展安全相关;
(5)不应该在jwt的payload部分存储敏感信息,因为该部分是客户端可解密的部分;
(6)保护好secret私钥。该私钥非常重要;
(7)如果可以,请使用https协议。
3.JWT和session的区别
相同点:是它们都是存储用户信息;
不同点:
(1)Session是在服务器端的,而JWT是在客户端的;
(2)Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销;而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力;
(3)Session的状态是存储在服务器端,客户端只有session id;而JWT的状态是存储在客户端。