JavaWeb基础 – Cookies与Session的区别
1.内容简介
在Java开发面试过程中这类问题也是经常被面试官问到,因此本章将会讲解Cookies与Session的区别,与此同时也会顺带讲解Token、JWT的区别。
2.C/S会话
2.1 产生原因
HTTP协议是无状态的,即每一次客户端和服务端完成回话时,服务端不会保存任何回话信息。因此HTTP发送的每一个请求都是独立的。独立的请求就会导致服务端无法确认当前发起请求的用户信息,同时也无法分别上一次请求和本次请求发送是否是同一个用户。服务器与浏览器为了进行回话跟踪,需要主动维护一个状态。这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。
2.2 Cookies
2.2.1 Cookie的性质
- 存储位置:Cookie存储在客户端浏览器上,其本身是服务器发送到用户浏览器并保存在本地的一小块数据,并且会在浏览器下次向同一服务器再次发起请求时被携带发送至服务器上。
- 跨域性:Cookie不可跨域,每个Cookie都会绑定单一的域名,无法在其他域名下使用。一级域名和二级域名之间是允许共享使用的(靠的是 domain)。
2.2.2 Cookie的属性
属性 | 说明 |
---|---|
name = value | 键值对,设置Cookie的名称和相应值,内容都为字符串。 |
domain | 指定Cookie所属域名,默认为当前域名。 |
path | 指定Cookie在那个路由下是生效的,默认为"/"。 |
maxAge | Cookie的失效时间,单位为秒。若为整数,则在maxAge后失效。若为负数则是临时Cookie |
expires | 过期时间,在设置的某个时间点后Cookie失效 |
secure | 该Cookie是否仅被使用安全协议传输,如HTTPS、SSL等。 |
httpOnly | 若给Cookie设置了httpOnly属性,则无法通过JS脚本读取信息,但并非绝对安全。 |
2.3 Session
2.3.1 Session的性质
- Session是另一种记录服务器与客户端回话状态的机制。
- Session是基于Cookie实现的,Session存储在服务器,而SessionId会被存入Cookie中。
2.3.2 Session认证流程
- 用户第一次请求服务器时,服务器根据用户提交的相关信息创建对应的Session。
- 请求返回时将该Session的唯一标识信息SessionId返回至浏览器。
- 浏览器接收到SessionId后将会存入Cookie中,并记录SessionId属于哪个域名。
- 当用户第二次访问时,会向服务器发送携带SessionId的Cookie,服务器根据ID查询对应Session信息,若没有找到则登录失败,若找到则可执行后续操作。
2.4 Token(令牌)
2.4.1 Access Token
- 访问API时所需的资源凭证
- 组成:UID、当前时间戳、签名(token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
- 特点:
- 服务端无状态化,可扩展性好
- 支持移动端设备
- 支持跨程序调用
- 验证流程
- 客户端使用用户名和密码请求登录。
- 服务端收到请求后去验证用户名和密码。
- 验证成功后服务端生成Token并发送至客户端。
- 客户端收到Token后会存储在本地。
- 客户端每次想服务端发起请求时都会携带Token
- 服务端接收请求后,先验证Token,若Token有效则返回数据
2.4.2 Refersh Token
Refresh Token 是专用于刷新 Access Token 的 Token。如果没有 Refresh Token,也可以刷新 Access Token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。
Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。
2.5 JWT(JSON Web Token)
JWT是目前最流行的烤鱼认证解决方案,是一种授权机制。JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。JWT加密可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。
- JWT认证流程如下:
- 用户输入用户名和密码登录,服务端认证成功后会返回给客户端一个JWT
- 客户端将Token保存至本地
- 当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样:
Authorization: Bearer
3.区别
3.1 Cookie与Session的区别
- 安全性:Session比Cookie更安全,Session存储在服务器而Cookie存储在本地。
- 存取类型:Cookie与Session存取值的类型不同,Cookie 只支持字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
- 有效期:Cookie与Session有效期不同,Cookie能保持较长的失效时间,而Session较短。
- 存储大小:单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
3.2 Token与Session的区别
- Session是一种记录服务端与客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而Token是访问API所需要的资源凭证。Token是服务端无状态化,不会存储会话信息。
- Session与Token并非对立,在身份认证过程中,Token比Session安全性高,因为每个请求都有签名,同时也能防止监听与重放攻击,而Session需要依赖链路层保障通讯安全。在使用Token时也可以加入Session实现有状态会话。
- 所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。简单来说,若需要实现三方数据共享如跳转登录等功能,则需要使用Token。若是在本网站内则使用哪种方式都无所谓。
3.3 Token与JWT的区别
-
相同点:
- 都是访问资源的令牌
- 都可以记录用户信息
- 都是使服务端无状态化
- 验证成功后,客户端才能访问服务端上受保护的资源
-
区别
- Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。
- JWT:将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。