一文让你搞懂cookie

一文让你搞懂cookie

不知道你是否了解 cookie,并且掌握了它的用法。

如果你像我以前一样,对 cookie 的概念也是略知一二,但是用起来却一筹莫展,那么此时此刻你是幸运的。

只要你跟随者我这篇文章的步伐,就能让你彻底的搞懂 cookie 了。

接下来,让我们言归正传吧。

什么是 cookie

首先让我们引用一段 mdn 上的 cookie 的定义

An HTTP cookie (web cookie, browser cookie) is a small piece of data that a server sends to the user’s web browser. The browser may store it and send it back with the next request to the same server. Typically, it’s used to tell if two requests came from the same browser — keeping a user logged-in, for example. It remembers stateful information for the stateless HTTP protocol.

简单点说来,cookie 就是服务器发送给客户端,用来标识访问的用户的这么一个标识,可以理解为身份令牌吧。

可能这么说还是不太好理解,那么我就举个生活中的小例子来说明吧。

如果把服务器比做银行,那么客户端就可以看作是,到银行去取钱的人,而 cookie 这个时候,就可以看作是银行卡。

而银行卡,当然是有对应的银行发行的,用来标识客户的唯一身份的。

cookie 也是这个作用,用来标识请求的页面的用户的身份信息用的。

只要用了 cookie,每一次请求数据,都会携带这个 cookie,而服务器则会根据这个 cookie 的状态,判断,用户是否有权限执行对应的请求操作。

可以说,有了 cookie 就很方便了,我们不用每次都询问用户是谁,因为 cookie 会告诉我们答案。

而且,一般来说,cookie 也用于简化用户的网站使用体验,比如有了 cookie 信息,客户端就可以用来判断,用户是谁,不用每次重新开启页面,都进行登陆操作。

但是有些时候,cookie 也会泄露用户的隐私,比如网站会用 cookie 来记录,用户浏览过哪些网页,这对于有些应用场景下是有必要的,但是在有些场景下,则会给用户带来烦恼。

比如有时候,你不小心点开了,网站推荐的商品,结果,后来你每次进来,网站都给你推荐类似的商品。

这就是广告,当 cookie 遇上广告,被用作营销牟利的工具的时候,技术也就变味了。

让我们先回归到 cookie 这项技术本身来吧。

cookie 一般不会存在兼容性问题,所有的现代的浏览器,都对 cookie 进行了支持。

在前端,我们可以通过 document.cookie 来获取当前页面的 cookie,当然更为友好的方式,是通过浏览器的开发者工具来查看当前页面的 cookie 信息。

截屏2019-12-0600.13.50.png

比如上图,就是用 Chrome 的 devtools 工具,查看的 cookie 信息。

cookie 可以有多条,而一般一条 cookie 则由 name、value、domain、expires 等等信息组成。

前端操作 cookie

前端最原始的设置 cookie 的方式就是通过 documet.cookie = "test=123;" 然后,再通过 document.cookie 来查看 cookie,便会发现我们设置的测试 cookie 赫然出现在我们的结果之中。

直观上,这好像与我们的 js 语法相违背!

document.cookie 本身是一个字符串。

怎么我给 cookie 设置值,他的值不是覆盖而是拼接到属性上去了呢。

如果熟悉 es5 的 getter/setter 的同学一定深谙其道,这不就是一个 getter/setter 属性么。

而删除 cookie,则是通过设置 cookie 的过期时间为现在,就会将对应的 cookie 给删除掉。

后端使用 cookie

后端使用 cookie,则是通过在请求的回复中,设置请求头中的 cookie 的方式来进行设置的。

比如下面,👇,就是在 nodejs 中使用 cookie 的方式:

response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);

这样设置了以后,就能在 http 的回复头中获取到 cookie 了。

我们看看浏览器接收到的 response 的请求头:

HTTP/1.1 200 OK
Content-Type: text/plain
Set-Cookie: type=ninja
Set-Cookie: language=javascript
Date: Thu, 05 Dec 2019 17:26:28 GMT
Connection: keep-alive
Transfer-Encoding: chunked
X-DNS-Prefetch-Control: off

我们设置了 cookie 以后,默认情况下,以后每次请求的时候,都会自动带上 cookie。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cache-Control: max-age=0
Connection: keep-alive
Cookie: type=ninja; language=javascript
DNT: 1
Host: localhost:3002
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36

跨域的处理

以上内容都很好懂,只要自己多揣摩几次,就会明白其中的缘由。

但是对于跨域的情况下 cookie 的处理,是我们需要掌握的一个重点内容。

跨域代表着不可控,也就是,通过 xhr 请求,来获取数据,并且客户端页面的域名不是服务器的域名。

不跨域,说明页面是从同一个域名读取的。

也就是说,在一定程度上,服务器对其内容是可以信赖的,可以放心的提供数据。

所以为了安全起见,一般浏览器都对此做了限制,限制前端直接对后端设置的 cookie 进行修改、读取等操作,但是当浏览器向后端请求的时候,却能够自动的携带上cookie,用来验证身份。

所以在这个话题上,我们对于跨域的处理,主要是针对于后端的。

因为前端,对于跨域的 cookie,确实是无能为力的。

当然,因为博主本身是一名前端,最熟悉的后端语言是 nodejs,因此,这个话题,主要针对的是 nodejs 对于前端跨域的处理。

一般情况下,最简单的,当然是直接允许所有的域名,都能通过。

app.use(
  cors({
    origin: '*',
    credentials: true,
  }),
);

当然,以上代码是在 express 中的设置方式,如果你用的是别的框架或者原生的,其实原理都差不多。

如果这样用了,那么 cookie 是设置不了的。

所以,必须要设置某些域名能够通过跨域验证:

app.use(
  cors({
    origin: [
      'http://localhost:3000',
      'http://localhost:3001',
      'http://localhost:8080',
    ],
    credentials: true,
  }),
);

这个域名,不是指服务器的域名,而是指,前端静态资源所处的服务器的域名。

理解这一点很重要,很多人在这个地方都搞不清楚,或者似懂非懂。

其实 cookie 很简单,内容并不多,关键是要在实战中,多用,然后才能真正的掌握这个利器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章