Skip to content
On this page

什么是 cookie

由于 HTTP 是无状态协议,但是比如一个网站我不可能每打开一个页面都登陆一次吧。总要有一个东西来记录用户的状态~。这时候 cookie就诞生了。

javascript
// 完整格式如下
Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"

其中 name=value是一个必填项

domain

这里可以设置 cookie 对于哪个域是有效的。值得注意的是这个值可以包含子域。比如 domain=.taobao.com那么他的子域A.taobao.com 又或者是 B.taobao.com 都可以访问。但是如果设置了A.taobao.com那么只有A.taobao.com这个域才能获取到这个 cookie。

path

类似 domain 但是 path 对应得是路径,可以设置/login那这个路径下包括/login/xxx都可以访问到这个 cookie

expires

过期时间,和 max-age 一样都是临时会话的时间。 max-age 是秒数。如果两者同一时间出现则max-age的优先级更高。cookie 的生命周期默认为 session,即浏览器关闭后删除。如果设置了 expires,则由 expires 控制,如果浏览器关闭还没到过期时间,则会保存在硬盘中

HttpOnly

JS脚本是否可以获取(默认可以获取,为false)。如果设置为true则可以有效防止XSS攻击。该属性只能在服务的设置

Secure

S 脚本是否可以获取(默认可以获取,为 false)。若为 true,那么 Cookie 只能在 HTTPS连接中传输;若为 false,HTTP、HTTPS 连接都行。

Samesite

  • None 同站请求、跨站请求发送cookie,但是在 chrome80+以后,设置为None需要同时设置Secure,也就意味着必须要https连接。
  • Strict 仅发送同站点的请求的 cookie
  • Lax Chrome80 后默认为这个值。仅get请求跨站。大多数情况也是不发送第三方 cookie。 包括三种情况:链接,预加载请求,get 表单

设置为 Lax,Strict可以杜绝大部分csrf攻击

跨域跨站

其中同站(same-site)/跨站(cross-site)」和第一方(first-party)/第三方(third-party)是等价的。

举几个例子,www.taobao.comwww.baidu.com 是跨站,www.a.taobao.comwww.b.taobao.com 是同站,a.github.iob.github.io 是跨站(注意是跨站)。

session 是服务端的一种机制,使用类似散列表的数据结构来保存用于用户信息,如登录状态。
cookie 则可以用于服务端保存登录状态,比如为客户端设置 cookie 来保存 session 对应的 sessionID,下次请求时客户端自动携带 cookie,服务的从中取出 sessionID,在从 session 表中获取用户登录状态及用户信息。

token 是另一种流行的处理 http 无状态的方式,一般设置在请求头中。当用户登录成功时返回 token 给客户端,客户端再次请求时携带 token,服务端获取 token 后,再从 session 中获取用户信息及登录状态。
cookie 相比,因为 token 在代码中设置,不会在访问第三方网站时携带 cookie,可以有效避免 csrf 攻击。

  • cookie 的大小一般被浏览器限制为 4kb
  • 请求自动携带 cookie 其实会造成无效的带宽浪费
  • 安全问题(csrf 与 xss)

XSS 攻击

xss攻击就是跨站脚本攻击。一般可以分为三类,我认为实际上可以分为两类存储型和非存储型

反射型

反射型一般构造在url中。如果服务端中没有做过处理,直接将内容返回给客户端则会触发在url中隐藏的<script></script>代码。形如

javascript
www.baidu.com?<srcipt>alert('xss')</script>

但是这样主要还是需要构造url然后去触发。

存储型

存储型就是将xss攻击保存到数据库中。比如我一个评论中注入恶意代码

javascript
<img onerror="alert('xss')" src="">

这样存储在数据库的攻击危害是最大的。因为每一个见到这个评论的人都会受到攻击。

DOM 型

DOM型实际上是最难的,因为他需要构造一个带有XSS攻击的 DOM。然后诱导用户去操作才会触发。

XSS 注入方法

HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
在内联的 JavaScript中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
onload、onerror、onclick 等事件中,注入不受控制代码。
style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。
style 属性和标签中,包含类似 expression(...)的 CSS 表达式代码(新版本浏览器已经可以防范)。

解决办法

  • 对用户提交的可能存在 xss 攻击的地方进行转义,服务端中也需要。
  • 服务端在http中设置set-cookie:Httponly
  • innerTextsetAttribute()代替innerHtml

CSRF 攻击

CSRF攻击就是跨站请求伪造,简单点就是我冒用你的身份去做你不知道的事情。
比如之前的钓鱼网址就是。比如小明登陆了 A 网站。这时候 A 网站就会有小明的cookie。小明再被我诱导点击我写好document.cookie的空页面。一进入这个页面就会拿到小明的cookie并且去请求 A 网站的接口做一些坏事。因为我用的是小明的cookie这样就是我冒用小明对他造成了一系列损失。

解决办法

  • 在服务端中设置 SameSite 为LUX,这样因为我的网站是相对于 A 来说是第三方网站。即便是<a>跳转的。请求时也不会携带 cookie。
  • 判断请求头中的Origin Header Referer Header检测是否同源。(协议,域名,端口完全相同)
    这两个 Header 在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。 服务器可以通过解析这两个 Header 中的域名,确定请求的来源域。
    Origin Header请求的 Header 中会携带 Origin 字段。字段内包含请求的域名(不包含 path 及 query)。
    Referer Header在 HTTP 头中有一个字段叫 Referer,记录了该 HTTP 请求的来源地址。
    对于 Ajax 请求,图片和 script 等资源请求,Referer 为发起请求的页面地址。对于页面跳转,Referer 为打开页面历史记录的前一个页面地址。因此我们使用 Referer 中链接的 Origin 部分可以得知请求的来源域名。
  • 采用token