系统设计面试总结:2、认证Authentication(下):没有Cookie时Session还能用吗?为什么Cookie无法防止CSRF攻击,而Token可以?

仅供自学回顾使用,请支持javaGuide原版。

如果没有 Cookie 的话 Session 还能用吗?

一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作。

但是,并不是没有 Cookie 之后就不能用 Session 了,比如你可以将 SessionID 放在请求的 url 里面https://javaguide.cn/?Session_id=xxx 。

这种方案的话可行,但是安全性和用户体验感降低。当然,为了安全你也可以对 SessionID 进行一次加密之后再传入后端。

为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?

CSRF(Cross Site Request Forgery) 一般被翻译为 跨站请求伪造
那么什么是跨站请求伪造呢?其实就是用你的身份去发送一些对你不友好的请求。

javaGuide原文提到原因如下:

上面也提到过,进行 Session 认证的时候,我们一般使用 Cookie 来存储 SessionId,当我们登陆后,后端生成一个 SessionId 放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个SessionId

客户端登录以后每次请求都会带上这个 SessionId,服务端通过这个 SessionId 来标示你这个人。如果别人通过 Cookie 拿到了 SessionId 后就可以代替你的身份访问系统了。

但是,我们使用 Token 的话就不会存在这个问题,在我们登录成功获得 Token 之后,一般会选择存放在localStorage (浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题。因为,即使你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token 的,所以这个请求将是非法的。

简化解释来讲就是,使用Cookie存储SessionId时,浏览器会自动发送Cookie,攻击者可利用这一点,通过诱导用户点击恶意链接,冒用用户身份发起请求(CSRF攻击)。

Token存储在localStorage中,不会自动发送。每个请求需手动添加Token,恶意链接无法获取和发送Token,因此无法冒用用户身份,有效防止CSRF攻击

扫描二维码关注公众号,回复: 17549439 查看本文章

我本人更喜欢以下的解释,Cookietoken的区别会更清楚一点:

Cookie无法防止CSRF攻击的原因:

  • 自动发送:当用户访问某个网站时,浏览器会自动发送与该网站相关的Cookie。这意味着即使请求是由攻击者构造的,只要用户已经登录过目标网站,Cookie就会自动包含在请求中,从而被攻击者利用。
  • 通常缺乏请求特异性:Cookie通常是用于身份认证的,它们一般不特定于某个请求或会话(除非特意设置了Cookiepath属性)。因此它一般会在所有符合条件的请求中被发送,这为CSRF攻击提供了可乘之机。
  • 通常在客户端长期存储:Cookie一般会在客户端存储较长时间段。在该时间段内,用户登录已登录的网站,Cookie不变。

Token可以防止CSRF攻击的原因:

  • 需要主动提交:Token需要开发者显式地在请求中提交(譬如由前端注入),而不是由浏览器自动发送。这增加了攻击者构造有效请求的难度,因为它们需要知道Token的值并将其包含在请求中。
  • 请求特异性:Token通常是针对每个请求或会话生成的,其可以和特定请求参数或HTTP头结合,从而具有唯一性。这意味着即使攻击者知道了某个Token,它也只能用于特定的请求,而不能用于其他请求。
  • 通常不在客户端长期存储:Token通常不会在客户端长期存储。即使登陆过相同网站,可能第二次登录时服务器就生成了新的Token交由客户端。

需要注意的是:不论是 Cookie 还是 Token 都无法避免 跨站脚本攻击(Cross Site Scripting)XSS

跨站脚本攻击(Cross Site Scripting)缩写为 CSS 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为 XSS

XSS 中攻击者会用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如 Cookie