Cookie、Session、Token 、JWT、单点登录 详解

HTTP是无状态说起,因为 HTTP 请求方和响应方间无法维护状态,都是一次性的,它不知道前后的请求都发生了什么。但在有些应用场景下,我们需要维护用户状态,比如登录状态,最典型的,一个用户登陆微博,发布、关注、评论,都应是在登录后的用户状态下的。

一、“前端”标记方式:Cookie 

Cookie是服务端发送到用户浏览器并且保存到本地的一小块数据,它会在浏览器下次向同一服务器发起请求时,被携带到服务器上。

  • 经常用来做一些用户会话状态管理、个性化设置等等。
  • cookie是跨域的,也就是在不同的域名中,访问的cookie的时候,只能访问对应的域名的cookie。

CSRF(跨站伪造请求)

用户登陆了a网站(后续所有请求都携带a网站的Cookies),然后跳转到b网站,b网站直接发送一个a网站的请求(b网站发送带a网站Cookies的请求,因此称为“伪造”),进行一些危险操作,就发生了CSRF攻击!

  • 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
  • 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。

最好的办法是使用Token。一般情况下我们使用 JWT 的话,在我们登录成功获得 JWT 之后,一般会选择存放在 localStorage 中。前端的每一个请求后续都会附带上这个 JWT,整个过程压根不会涉及到 Cookie。因此,即使你点击了非法链接发送了请求到服务端,这个非法请求也是不会携带 JWT 的,所以这个请求将是非法的。

XSS(跨站脚本攻击)

XSS是由于不安全的数据引起的,有可能是表单提交的数据,有可能是页面路径的参数问题。

  • XSS是通过盗取用户的敏感信息而达到攻击的目的

常见的避免 XSS 攻击的方式是过滤掉请求中存在 XSS 攻击风险的可疑字符串。

在 Spring 项目中,我们一般是通过创建 XSS 过滤器来实现的。

二、“前后端”状态管理方案:Session

Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。

cookie是实现session认证的一种途径

Session 的分布式问题

通常服务端是集群,而用户请求过来会走一次负载均衡,不一定打到哪台机器上。那一旦用户后续接口请求到的机器和他登录请求的机器不一致,或者登录请求的机器宕机了,session 不就失效了吗?

这个问题现在有几种解决方式。

  • 一是从「存储」角度,把 session 集中存储。如果我们用独立的 Redis 或普通数据库,就可以把 session 都存到一个库里。
  • 二是从「分布」角度,让相同 IP 的请求在负载均衡时都打到同一台机器上。以 nginx 为例,可以配置 ip_hash 来实现。

但通常还是采用第一种方式,因为第二种相当于阉割了负载均衡,且仍没有解决「用户请求的机器宕机」的问题。

三、“前端”状态管理方案:token

cookie 并不是客户端存储凭证的唯一方式。token 因为它的「无状态性」,有效期、使用限制都包在 token 内容里,对 cookie 的管理能力依赖较小,客户端存起来就显得更自由。但 web 应用的主流方式仍是放在 cookie 里,毕竟少操心。

token 的流程是这样的:

  • 用户登录,服务端校验账号密码,获得用户信息
  • 把用户信息、token 配置编码成 token,通过 cookie set 到浏览器
  • 此后用户请求业务接口,通过 cookie 携带 token
  • 接口校验 token 有效性,进行正常业务接口处理

总结

狭义上,我们通常认为 session 是「种在 cookie 上、数据存在服务端」的认证方案,token 是「客户端存哪都行、数据存在 token 里」的认证方案。对 session 和 token 的对比本质上是「客户端存 cookie / 存别地儿」、「服务端存数据 / 不存数据」的对比。

客户端存 cookie / 存别地儿

存 cookie 固然方便不操心,但问题也很明显:

  • 在浏览器端,可以用 cookie(实际上 token 就常用 cookie),但出了浏览器端,没有 cookie 怎么办?
  • cookie 是浏览器在域下自动携带的,这就容易引发 CSRF 攻击

存别的地方,可以解决没有 cookie 的场景;通过参数等方式手动带,可以避免 CSRF 攻击。

服务端存数据 / 不存数据

  • 存数据:请求只需携带 id,可以大幅缩短认证字符串长度,减小请求体积
  • 不存数据:不需要服务端整套的解决方案和分布式处理,降低硬件成本;避免查库带来的验证延迟

四、token 生成方案:JWT(JSON Web Token)

JSON Web Token (JWT) 是一个开放标准,定义了一种传递 JSON 信息的方式。这些信息通过数字签名确保可信。

JWT 本质上就是一组字串,通过(.)切分成三个为 Base64 编码的部分:

  • Header(头部) : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。Header 被 Base64Url 编码后成为 JWT 的第一部分。
  • Payload(载荷) : 用来存放实际需要传递的数据,包含声明(Claims),如sub(subject,主题)、jti(JWT ID)。Payload 被 Base64Url 编码后成为 JWT 的第二部分。Payload 部分默认是不加密的,一定不要将隐私信息存放在 Payload 当中!!!
  • Signature(签名):服务器通过 Payload、Header 和一个密钥(Secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。生成的签名会成为 JWT 的第三部分。JWT 安全的核心在于签名,签名安全的核心在密钥。

两点建议:

  1. 建议将 JWT 存放在 localStorage 中,放在 Cookie 中会有 CSRF 风险。
  2. 请求服务端并携带 JWT 的常见做法是将其放在 HTTP Header 的 Authorization 字段中(Authorization: Bearer Token)。

如何加强 JWT 的安全性?

  1. 使用安全系数高的加密算法。
  2. 使用成熟的开源库,没必要造轮子。
  3. JWT 存放在 localStorage 中而不是 Cookie 中,避免 CSRF 风险。
  4. 一定不要将隐私信息存放在 Payload 当中。
  5. 密钥一定保管好,一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。
  6. Payload 要加入 exp (JWT 的过期时间),永久有效的 JWT 不合理。并且,JWT 的过期时间不易过长。

五、单点登录——「一次登录,全线通用」

  • “虚假”的单点登录(主域名相同):如果业务系统都在同一主域名下,比如wenku.baidu.com tieba.baidu.com,就好办了。可以直接把 cookie domain 设置为主域名 baidu.com,百度也就是这么干的。

  • “真实”的单点登录(主域名不同):比如滴滴这么潮的公司,同时拥有didichuxing.com xiaojukeji.com didiglobal.com等域名,种 cookie 是完全绕不开的。这要能实现「一次登录,全线通用」,才是真正的单点登录。这种场景下,我们需要独立的认证服务,通常被称为 SSO。

  • 用户进入 A 系统,没有登录凭证(ticket),A 系统给他跳到 SSO
  • SSO 没登录过,也就没有 sso 系统下没有凭证(注意这个和前面 A ticket 是两回事),输入账号密码登录
  • SSO 账号密码验证成功,通过接口返回做两件事:一是种下 sso 系统下凭证(记录用户在 SSO 登录状态);二是下发一个 ticket
  • 客户端拿到 ticket,保存起来,带着请求系统 A 接口
  • 系统 A 校验 ticket,成功后正常处理业务请求
  • 此时用户第一次进入系统 B,没有登录凭证(ticket),B 系统给他跳到 SSO
  • SSO 登录过,系统下有凭证,不用再次登录,只需要下发 ticket
  • 客户端拿到 ticket,保存起来,带着请求系统 B 接口

六、参考 

你真的了解 Cookie 和 Session 吗 - 掘金 (juejin.cn)
Cookie的设置、读取以及是否自动携带问题 - 掘金 (juejin.cn)
前后端数据交互(六)——ajax 、fetch 和 axios 优缺点及比较 - 掘金 (juejin.cn)
面试:彻底理解Cookie以及Cookie安全 - 掘金 (juejin.cn)
前端鉴权的兄弟们:cookie、session、token、jwt、单点登录 - 掘金 (juejin.cn)
HTTP协议之涉及到cookie字段 - 掘金 (juejin.cn)
/juejin.cn/post/6844904102544031757)
前端鉴权的兄弟们:cookie、session、token、jwt、单点登录 - 掘金 (juejin.cn)
HTTP协议之涉及到cookie字段 - 掘金 (juejin.cn)
原文链接:https://blog.csdn.net/klji234/article/details/124314796

  • 16
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值