本文的主题是使用Node.js架设一个服务,看看Cookie的实际应用场景环境配置。我们新建一个文件main.js,在main.js中写入如下代码:constexpress=require('express')constapp=express()app.listen(3000,err=>{if(err){returnconsole.log(err)}console.log('----打开http://localhost:3000----')})app.get('/',(req,res)=>{res.send('
helloworld!
')})nodemain.js//本地服务正在运行,现在打开http://localhost:3000//可以看到大大的helloworld!Cookies的工作原理在介绍什么是Cookies之前,我们先来看一下Cookies的工作原理:1、首先我们假设当前域名下没有cookies。2.接下来浏览器向服务器发送请求(这个请求还没有带cookies)3.服务器设置cookie并发送给浏览器(当然你也可以不设置)4.浏览器保存cookie5.接下来,后续的每一次请求都会带上这些cookie,发送给服务器进行校验。我们来验证一下。//修改main.jsapp.get('/',(req,res)=>{//服务端收到请求,为响应设置一个cookie//这个cookie的名字是testName//值为testValueres.cookie('testName','testValue')res.send('
helloworld!
')})//保存后重启服务器//nodemain.js现在打开http:///localhost:3000我们看到请求标头并且没有Cookie字段但是ResponseHeaders有Set-Cookie字段。现在我们刷新页面,相当于重新向http://localhost:3000/地址发起请求。现在我们可以看到Cookie字段已经带上了,再刷新几次就可以看到Cookie还在。document.cookieJS提供了获取cookie的方法:document.cookie,我们先多设置几个cookie。app.get('/',(req,res)=>{res.cookie('testName0','testValue0')res.cookie('testName1','testValue1')res.cookie('testName2','testValue2'')res.cookie('testName3','testValue3')res.send('
helloworld!
')})我们可以看到cookie是一个字符串。但是这个字符串是格式化的,由以分号和空格分隔的键值对key=value组成。什么是cookie说了这么多,大家应该知道什么是cookie了吧。梳理一下,有以下几点:Cookie是浏览器存储在用户电脑上的一个短文本文件。Cookie为纯文本格式,不包含任何可执行代码。Cookie由以分号和空格分隔的键值对组成,虽然它存储在浏览器中,但通常由服务器设置。cookie的大小限制在4kb左右。cookie的属性选项每个cookie都有一定的属性,比如什么时候过期,发送到哪个域名,哪个路径等等,这些属性可以在设置任何cookie的时候设置,或者不设置,默认值是这些属性将被使用。expires/max-ageexpires/max-age是控制cookie过期时间的选项。如果不设置这两个选项,则默认有效期为session,即会话cookie。该cookie在浏览器关闭后消失。expiresexpires选项用于设置cookie何时有效,expires实际上是cookie的过期日期。expires必须是GMT格式的时间(可以通过newDate().toGMTString()或newDate().toUTCString()获取)app.get('/',(req,res)=>{//thiscookieRes.cookie('testName0','testValue0',{expires:newDate(Date.now()+10000)})//这个cookie没有设置过期时间res.cookie('testName1','testValue1')res.send('
helloworld!
')})上面代码服务器设置了两个cookie,一个有过期时间,一个没有设置,也就是默认的过期时间session。现在我们重启服务并刷新页面。现在响应头增加了响应设置过期时间字段。在控制台中输入以下代码。console.log(`当前cookie为:${document.cookie}`)setTimeout(()=>{console.log(`5秒后cookie为:${document.cookie}`)},5000)setTimeout(()=>{console.log(`10秒后的cookie是:${document.cookie}`)},10000)所以cookie过期后,就无法通过document.cookie访问cookie了,当然??,以后发送请求不会再带这个无效的cookie。max-ageexpires是http/1.0协议中的一个选项。在新的http/1.1协议中,expires已被max-age选项取代。两者的作用都是限制cookie的有效时间。expires的值是一个时间点(Cookie过期时间=expires),max-age的值是一个时间段,以秒为单位(Cookie过期时间=创建时间+max-age)//设置max-age就是设置从创建cookie的那一刻开始计算//多少秒后cookie将过期app.get('/',(req,res)=>{res.cookie('testName0','testValue0',{//expressthis参数以毫秒为单位//实际发送给浏览器会转换为秒//十秒后过期maxAge:10000})res.cookie('testName1','testValue1')res.send('
helloworld!
')})Priority如果同时设置了max-age和expires,则以max-age时间为准。app.get('/',(req,res)=>{res.cookie('name0','value0')res.cookie('name1','value1',{expires:newDate(Date.now()+30*1000),maxAge:60*1000})res.cookie('name2','value2',{maxAge:60*1000})res.send('
helloworld!
')})域和路径名,域和路径可以标识一个唯一的cookie。domain和path选项共同决定浏览器何时自动将cookie添加到请求标头并发送。具体原理请参考Cookie的作用域和路径章节。如果两个选项都没有设置,则使用默认值。domain默认值为设置cookie的网页域名,path默认值为设置cookie的网页目录。secure选项用于将cookie设置为仅在安全请求中发送。只有当请求是HTTPS或其他安全协议时,包含安全选项的cookie才能保存到浏览器或发送到服务器。默认情况下,cookie将没有安全选项(即空)。所以默认情况下,不管是HTTPS协议请求还是HTTP协议请求,都会向服务器发送cookies。httpOnly选项用于设置cookie是否可以通过js访问。默认情况下cookie没有httpOnly选项(即为空),客户端可以通过js代码访问(包括读取、修改、删除等)cookie。当cookie有httpOnly选项时,客户端无法通过js代码访问(包括读取、修改、删除等)cookie。看一下代码,修改main.js,保存重启服务,刷新页面。app.get('/',(req,res)=>{res.cookie('notHttpOnly','testValue')res.cookie('httpOnlyTest','testValue',{httpOnly:true})res.send('
helloworld!
')})看图,设置了httpOnly的cookie多了一个勾。并且无法通过document.cookie访问该cookie。无法通过js代码在客户端设置一个httpOnlycookie。这种类型的cookie只能在服务器端设置。发送请求时,我们看到请求头中仍然会携带httpOnlycookie,如下图。设置cookie很明确:cookie可以由服务器设置,也可以由客户端设置。看到这里,相信大家都能理解了。服务端设置cookie回看刚才的图片,我们设置了很多cookie。一个Set-Cookie字段只能设置一个Cookie。当要设置多个Cookie时,需要添加相同数量的Set-Cookie字段。服务端可以设置Cookie的所有选项:expires,domain,path,secure,HttpOnly客户端设置我们也可以在网页中通过js代码设置cookies,即客户端。setdocument.cookie='name=value'设置Cookie的以下选项:expires,domain,path,必须使用所有键值对;用空格分隔document.cookie='name=value;expires=2116年2月26日星期四11:50:25GMT;域名=三快网;path=/';secure只有在https协议的网页中,客户端才能成功设置cookie的安全类型。HttpOnly不能在客户端设置HttpOnly选项来删除CookieCookie的名称、路径和域是唯一标识一个cookie的。只要我们将一个cookie的max-age设置为0,就可以删除一个cookie。letremoveCookie=(name,path,domain)=>{document.cookie=`${name}=;路径=${路径};域名=${域名};max-age=0`}Cookie作用域和Scopeofactionpath在讲这个作用域之前,我们先对域名做一个简单的了解。子域是指域名中相对于父域的各个部分。每个子字段由小数点分隔。放在域名末尾的子域称为最高级别子域,或一级域,位于其前面的子域称为二级域。以下图为例,news.163.com和sports.163.com是子域,163.com是父域。当cookie的域是news.163.com时,访问news.163.com时会带cookie;当cookie的域是163.com时,那么访问news.163.com和sports.163.com都会是带cookie的Action路径当cookie的域相同时,是否带cookie是有一定规则的。访问父路径的Cookie可以在子路径中访问,但反之则不行。看例子,还是修改main.jsapp.get('/parent',(req,res)=>{res.cookie('parent-name','parent-value',{path:'/parent'})res.send('
parentpath!
')})app.get('/parent/childA',(req,res)=>{res.cookie('child-name-A','child-value-A',{path:'/parent/childA'})res.send('
childpathA!
')})app.get('/parent/childB',(req,res)=>{res.cookie('child-name-B','child-value-B',{path:'/parent/childB'})res.send('
子路径B!
')})这里的“域”要改成路径。参考文章说说cookie的范围以及cookie和session的使用方法。