我在平时开发和学习的过程中遇到过多种存储认证信息的方式,有把access_token存储到LocalStorage的,也有通过Cookie进行认证的,那我们平时应该选择哪种方式呢?接下来我将从游览器安全的方面进行一下两者的优劣对比。
首先我们得先知道常见的游览器安全问题有哪些:
XSS
定义
XSS 全称是 Cross Site Scripting,为了与“CSS”区分开来,故简称 XSS,翻译过来就是“跨站脚本”。XSS 攻击是指黑客往 HTML 文件中或者 DOM 中注入恶意脚本,从而在用户浏览页面时利用注入的恶意脚本对用户实施攻击的一种手段。简而言之,XSS就是恶意用户往目标网站中注入一些脚本,当你访问到了目标网站后之前的脚本就会在你的游览器上执行,达到攻击目的。
存在原因
浏览器为了在安全和自由之间找到一个平衡点。支持了页面中的引用第三方资源和 跨域资源共享(CORS),这样做带来了很多安全问题,其中最典型的就是 XSS 攻击。
攻击方式
- 存储型 XSS 攻击
- 首先黑客利用站点漏洞将一段恶意 JavaScript 代码提/交到网站的数据库中;
- 然后用户向网站请求包含了恶意 JavaScript 脚本的页面;
- 当用户浏览该页面的时候,恶意脚本就会执行
- 反射型 XSS 攻击
- 恶意 JavaScript 脚本属于用户发送给网站请求中的一部分。
- 随后网站又把恶意 JavaScript 脚本返回给用户。
- 恶意 JavaScript 脚本就可以在用户页面中被执行
- 基于 DOM 的 XSS 攻击
基于 DOM 的 XSS 攻击是不牵涉到页面 Web 服务器的。黑客通过各种手段将恶意脚本注入用户的页面中,比如通过网络劫持在页面传输过程中修改 HTML 页面的内容,这种劫持类型很多,有通过 WiFi 路由器劫持的,有通过本地恶意软件来劫持的,它们的共同点是在 Web 资源传输过程或者在用户使用页面的过程中修改 Web 页面的数据。
危害
- 窃取 Cookie 信息
窃取到Cookie后,就可以在其他电脑上模拟用户的登录。
- 监听用户行为
可以使用“addEventListener”接口来监听键盘事件
- 修改 DOM
可以通过修改 DOM 伪造假的登录窗口,用来欺骗用户输入用户名和密码等信息
防御
- 服务器对输入脚本进行过滤或转码
- 充分利用 CSP
实施严格的 CSP 可以有效地防范 XSS 攻击,具体来讲 CSP 有如下几个功能:
- 限制加载其他域下的资源文件
- 禁止向第三方域提交数据,这样用户数据也不会外泄;
- 禁止执行内联脚本和未授权的脚本;
- 还提供了上报机制,这样可以帮助我们尽快发现有哪些 XSS 攻击,以便尽快修复问题。
- 防止Cookie被盗用,使用 HttpOnly 属性
使用 HttpOnly 标记的 Cookie 只能使用在 HTTP 请求过程中,所以无法通过 JavaScript 来读取这段 Cookie。
CSRF
定义
CSRF 英文全称是 Cross-site request forgery,是指黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起的跨站请求。简单来讲,CSRF 攻击就是利用了用户的登录状态,并通过第三方的站点来做一些坏事。而且CSRF 攻击并不需要将恶意代码注入用户的页面,仅仅是利用服务器的漏洞和用户的登录状态来实施攻击
存在原因
利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
攻击方式
- 自动发起 Get 请求
- 自动发起 POST 请求
- 引诱用户点击链接
这几种攻击方式的前提
- 目标站点一定要有 CSRF 漏洞;
- 用户要登录过目标站点,并且在浏览器上保持有该站点的登录状态;
- 需要用户打开一个第三方站点,可以是黑客的站点,也可以是一些论坛。
危害
利用登陆态,可以做任何你登陆某网站后的操作,例如转账,更改信息等等
防御
- 充分利用好 Cookie 的 SameSite 属性
Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。他可以设置三个值
1.Strict
浏览器会完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
2.Lax
在跨站点的情况下Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。包括链接,预加载请求,GET 表单。而如果在第三方站点中使用 Post 方法,或者通过 img、iframe 等标签加载的 URL,这些场景都不会携带 Cookie。
3.None
在任何情况下都会发送 Cookie 数据,最新版本的Chrome中Lax变为默认设置。这时,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
- 验证请求的来源站点
根据HTTP 请求头中的 Referer 和 Origin 属性在服务器端验证请求来源的站点。Referer和Origin 都是 HTTP 请求头中的一个字段,
- Referer记录了该 HTTP 请求的来源地址。
- Origin属性只包含了域名信息,并没有包含具体的 URL 路径。
- 服务器的策略是优先判断 Origin,如果请求头中没有包含 Origin 属性,再根据实际情况判断是否使用 Referer 值。
- CSRF Token
- 在浏览器向服务器发起请求时,服务器生成一个 CSRF Token。CSRF Token 其实就是服务器生成的字符串,然后将该字符串植入到返回的页面中。
- 在浏览器端如果要发起某些请求,那么需要带上页面中的 CSRF Token,然后服务器会验证该 Token 是否合法。如果是从第三方站点发出的请求,那么将无法获取到 CSRF Token 的值,所以即使发出了请求,服务器也会因为 CSRF Token 不正确而拒绝请求。
localStroage VS Cookie
1. CSRF 攻击的影响
- Cookie 易受 CSRF 攻击
由于 Cookie 在同源请求中会自动携带,因此攻击者可以利用受害者的登录状态,伪造请求执行恶意操作(例如转账或更改密码)。 localStorage
不会自动携带,因此天然防 CSRF
localStorage
中的数据不会随着请求自动发送,攻击者不能直接利用受害者的身份凭证发起 CSRF 攻击。
2. XSS 攻击的影响
- Cookie(HttpOnly 模式下更安全)
-
如果
HttpOnly
标志被设置,JavaScript 无法访问 Cookie,即便 XSS 漏洞存在,攻击者也无法窃取 Cookie 。 -
但如果
HttpOnly
未开启,则document.cookie
仍然可以被恶意脚本读取。
-
localStorage
更容易受 XSS 影响-
localStorage
不能使用HttpOnly
,JavaScript 总是可以访问它。 -
如果站点存在 XSS 漏洞,攻击者可以直接读取
localStorage
并窃取存储的身份凭证(如token
)。 -
这使得
localStorage
在安全性上较cookie
更脆弱。
-
3. 使用场景与对比
特性 | Cookie | LocalStorage |
---|---|---|
是否自动发送 | 是,适用于身份验证 (session 方式) | 否,需手动添加到请求头 |
防 CSRF | 易受攻击,可使用 SameSite=strict 保护 | 天然防 CSRF |
防 XSS | 可通过 HttpOnly 限制访问 | 容易被 XSS 攻击 |
跨域访问 | 受 SameSite 和 CORS 限制 | 仅能访问同源数据 |
存储容量 | 约 4 KB | 约 5 MB |
4. 最佳实践
-
如果使用
cookie
(推荐方式)- 采用
HttpOnly
防止 XSS 窃取。 - 设置
Secure
,确保只有 HTTPS 连接才能传输cookie
。 - 采用
SameSite=Strict
或SameSite=Lax
限制跨站请求,降低 CSRF 风险。 - 如果
cookie
用于身份认证,可以配合 CSRF 令牌机制,确保请求是可信的。
- 采用
-
如果使用
localStorage
- 不能用于存储敏感信息(如
access_token
)。 - 需搭配 CSP(内容安全策略) 限制 JavaScript 代码来源,减少 XSS 风险。
- 建议使用 JWT + HttpOnly Cookie 来存储
refresh_token
,而access_token
放在memory
(避免持久存储)。
- 不能用于存储敏感信息(如
5. 结论
不能简单地用 localStorage
代替 cookie
来存储身份认证信息!
- cookie 在配合
HttpOnly
、Secure
、SameSite
等安全策略后,更适合存储身份凭证,避免 CSRF 和 XSS。 localStorage
可以用来存储一些非敏感的前端配置数据,而不适合作为身份认证的存储方案。
最安全的做法是:
-
使用
HttpOnly + Secure
cookie
存储refresh_token
(服务端可验证)。 -
仅在内存(
memory
)中存储access_token
,避免持久化存储(如localStorage
或sessionStorage
)。 -
配合 CSRF 令牌或
SameSite
保护 CSRF 攻击。
这样可以同时防止 CSRF 和 XSS,保证更好的安全性。
参考
https://www.cnblogs.com/suihang/p/13288540.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/CORS