共计 4493 个字符,预计需要花费 12 分钟才能阅读完成。
前言
最近应用 next.js 来开发前端网站,在登录环节发现 cookie 的存储和跨域存在问题,始终没弄懂 cookie 的原理,看了网上好多大佬的文章,大有播种分享给大家。
Cookie 介绍
HTTP cookie(Web cookie,浏览器 cookie)是服务器发送到用户 Web 浏览器的一小段数据。浏览器可能会存储 cookie 并将其与稍后的申请一起发送回同一服务器。通常,HTTP cookie 用于判断两个申请是否来自同一个浏览器——例如,让用户放弃登录状态。它为无状态 HTTP 协定 记住有状态信息。
Cookies 次要用于三个目标:
1、会话治理:如登录、购物车、游戏分数或服务器应记住的任何其余内容
2、个性化:如用户偏好、主题和其余设置
3、追踪:如记录和剖析用户行为
1、创立 cookie
接管到 HTTP 申请后,服务器能够发送一个或多个 Set-Cookie 响应头。浏览器通常存储 cookie 并将其与 Cookie HTTP 标头内的同一服务器的申请一起发送。您能够指定不应发送 cookie 的过期日期或时间段。您还能够对特定域和门路设置附加限度,以限度 cookie 的发送地位。
Set-Cookie 和 Header Cookie
HTTP 响应 (Response) 标头 (Header) 的 Set-Cookie 作用:从服务器发送 cookie 到用户代理。
一个简略的 cookie 设置如下:
Set-Cookie: <cookie-name>=<cookie-value>
这批示服务器发送标头通知客户端存储一对 cookie:
HTTP/2.0 200 OK
Content-Type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
而后,对于服务器的每个后续申请,浏览器都会应用标头将所有先前存储的 cookie 带回服务器 Cookie。
GET /sample_page.html HTTP/2.0
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
2、Cookie 的生命周期
cookie 的生命周期能够通过两种形式定义:
1、以后会话完结时:会删除会话 cookie。(浏览器定义“以后会话”何时完结,一些浏览器在重启时应用会话复原。这可能会导致会话 cookie 无限期地继续)
2、永恒 cookie:在 Expires 属性指定的日期或属性指定的一段时间后删除 Max-Age。
例如:
Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;
留神:
1、当您设置 Expires 日期和工夫时,它们与设置 cookie 的客户端相干,而不是服务器。
2、要删除 Cookie,须要将 Max-Age 设置为 0,并且将 Cookie 的值设置为 null。不要将 Max-Age 指令值设置为 - 1 正数。否则,浏览器会将其视为会话 cookie。
3、如果您的站点对用户进行身份验证,它应该从新生成并从新发送会话 cookie,即便是曾经存在的,只有用户进行身份验证。这种办法有助于避免会话固定攻打,第三方能够重用用户的会话。
3、限度对 cookie 的拜访
您能够通过以下两种形式之一确保 cookie 平安发送,并且不会被非预期方或脚本拜访:
1、Secure 属性
2、HttpOnly 属性。
带有该 Secure 属性的 cookie 仅通过 HTTPS 协定通过加密申请发送到服务器。它永远不会应用不平安的 HTTP 发送(本地主机 (localhost) 除外),这意味着中间人攻击者无奈轻松拜访它。不平安的站点(http: 在 URL 中带有)无奈应用该 Secure 属性设置 cookie。然而,不要假如这会 Secure 阻止对 cookie 中敏感信息的所有拜访。例如,有权拜访客户端硬盘(或 JavaScript,如果 HttpOnly 未设置该属性)的人能够读取和批改信息。
JavaScript API HttpOnly:无法访问具备该属性的 cookie;
Document.cookie 它只发送到服务器。
例如,继续存在于服务器端会话中的 cookie 不须要对 JavaScript 可用,并且应该具备该 HttpOnly 属性。这种预防措施有助于缓解跨站点脚本 (XSS) 攻打。
这是一个例子:
Set-Cookie: id=a3fWa; Expires=Thu, 21 Oct 2021 07:28:00 GMT; Secure; HttpOnly
4、定义 cookie 的发送地位
Domain 和 Path 属性定义了 cookie 的范畴:cookie 应该发送到哪些 URL。
4.1 Domain 属性
Domain 属性指定哪些主机能够接管 cookie。如果未指定,则该属性默认为设置 cookie 的同一主机,不包含 subdomains。
如果指定 Domain 则始终蕴含子域。因而,指定 Domain 比省略它的限度要小。然而,当子域须要共享无关用户的信息时,它会很有帮忙。
例如,如果您设置 Domain=mozilla.org,则 cookie 可用于子域,如 developer.mozilla.org.
4.2 Path 属性
Path 属性批示在申请的 URL 中必须存在的 URL 门路,以便发送 Cookie 标头。(%x2F”/”) 字符被视为目录分隔符,子目录也匹配。
例如,如果您设置 Path=/docs,则这些申请门路匹配:
/docs
/docs/
/docs/Web/
/docs/Web/HTTP
然而这些申请门路不会:
/
/docsets
/fr/docs
4.3 SameSite 属性
SameSite 属性容许服务器指定是否何时通过跨站点申请发送 cookie(其中站点由可注册域和计划定义:http 或 https)。这提供了一些针对跨站点申请伪造攻打 (CSRF) 的爱护。它须要三个可能的值:Strict、Lax 和 None。
应用 Strict 时,cookie 只会发送到它的起源站点。
Lax 相似,除了当用户导航到 cookie 的源站点时发送 cookie。例如,通过跟踪来自内部站点的链接。
None 指定在发动申请和跨站点申请时都发送 cookie,但仅在平安上下文中(即,如果还必须设置 SameSite=None 该属性)。
留神:如果未设置 SameSite 属性,则 cookie 默认被视为 Lax.
例子:
Set-Cookie: mykey=myvalue; SameSite=Strict
问题
介绍完 Cookie 之后,咱们假如咱们当初有个前后台拆散的我的项目,前端地址是:www.baidu.com,后盾 api 地址是:api.baidu.com 和 api.bilibili.com,当初咱们来剖析讲上面几个问题:
1、跨域前后台设置问题
2、跨域 Cookie 不能携带问题
3、Cookie 如何如何防止 XSS 攻打和 CSRF 攻打
1、跨域前后台设置问题
如果想让前端拜访后盾两个 api 地址咱们须要设置如下代码,
前端(以 axios 为例):
axios.defaults.withCredentials = true
后盾(以 spring cloud gateway 为例)
spring:
cloud:
loadbalancer.ribbon.enabled: false
gateway:
globalcors:
#add-to-simple-url-handler-mapping: true
cors-configurations:
'[/**]':
allowedHeaders: "*"
allowCredentials: true
allowedOrigins:
- "https://api.baidu.com"
- "https://api.bilibili.com"
allowedMethods: "*"
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
2、跨域 Cookie 不能携带问题
这里就有意思了,因为咱们前端的地址是 www.baidu.com,简称 A,后盾 api 有两个地址:api.baidu.com,简称 B 和 api.bilibili.com,简称 C,当咱们通过 A 申请 B 的接口的时候,cookie 会主动带上,因为他们是属于同源不同域,所以你在 A 下设置的 cookie 在申请 B 时也会带上,而当 A 申请 C 时就带不了了,显著两个不同源也不同域,所以无奈带上,如果真要带的话,只有当 A 申请 C 时会把 C 的 cookie 带给 C,而不能把 A 的 cookie 带给 C,所以当初你晓得该怎么做了吧!
3、Cookie 如何防止 XSS 攻打和 CSRF 攻打
XSS 介绍:
(Cross Site Script)攻打全称为跨站脚本攻打,xss 攻打通常指的是利用网页开发留下的破绽,通过奇妙的办法注入歹意的指令代码到网页上,使用户加载并执行歹意制作的网页程序。这些歹意网页程序通常是 JavaScript 代码
XSS 解决:
应用 Cookie 的 HttpOnly 属性
严格来说,HttpOnly 并非是为了反抗 XSS-HttpOnly 解决的是 XSS 后的 Cookie 劫持攻打。后面说了 XSS 可能会窃取用户的 Cookie,而后就间接登录了该用户的账户,然而如果 Cookie 设置了 HttpOnly, 则这种攻打会失败,因为 JavaScript 读取不到 Cookie 的值。
CSRF 介绍:
CSRF 攻打的全称是跨站申请伪造(cross site request forgery),是一种对网站的歹意利用。简略点讲就是,歹意网站 (攻击者) 盗用了你的身份,以你的名义向信赖网站发送歹意申请。CRSF 能做的事件包含利用你的身份发邮件、发短信、进行交易转账等,甚至盗取你的账号。
CSRF 攻打的三个必要条件:
指标站点肯定要有 CSRF 破绽
用户要登录过指标站点,并且在浏览器上放弃有该站点的登录状态
须要用户关上一个第三方站点,能够是黑客的站点,也能够是一些论坛
CSRF 攻打不会往页面注入歹意脚本,而是找服务器的破绽,因而黑客是无奈通过 CSRF 攻打来获取用户页面数据的,对于 CSRF 攻打,次要的防护伎俩是晋升服务器的安全性。
CSRF 解决:
如果是从第三方站点发动的申请,那么须要浏览器禁止发送某些要害 Cookie 数据到服务器;
如果是同一个站点发动的申请,那么就须要保障 Cookie 数据失常发送。
而 Cookie 中的 SameSite 属性正是为了解决这个问题的。
在 HTTP 响应头中,通过 set-cookie 字段设置 Cookie 时,能够带上 SameSite 选项。
总结
1、cookie 是所有前端开发人员必须要面对的知识点,大家肯定要把原理弄清楚,这样在理论开发中遇到跨域还是 xss、csrf 攻打防备的话都可能对症下药
援用
应用 HTTP cookie
浏览器原理 33 # CSRF 攻打:为什么 Cookie 中有 SameSite 属性?
【信息安全】面试常问 CSRF、cookie、session 和 token
浏览器跨域申请胜利了,然而 cookie 没有带过来,求解?