浏览器和Webserver之间的关系,被设计为无状态的,这是一个很重要的设计,可以让客户端无需和服务器保持状态,节省宝贵的端口资源,从而可以为更多的客户链接服务。
但是这样带来了问题,简言之,服务器无法知道两个请求是否来自于同一个浏览器。然而,在页面访问计数,购物车等应用中,服务器是需要区分不同的浏览器的,比如客户浏览器1放置到购物车内的商品,和客户2浏览器的不可以混杂在一起。
办法是有的。比如在请求的页面中插入一个 token,然后在下次请求时将这个 token 返回至服务器。可以把token放到form内或者URL参数内。
但是被广为接受的是Cookie方法。cookie就是根据服务器响应头的指示,浏览器保存的一段文本。并在随后的请求中将这些信息发送至Web服务器,Web服务器就可以使用这些信息来识别不同的用户。
具体做法就是:
- 服务器可以为来访的浏览器设置一个值,这个通过response内的Set-Cookie来实现
- 浏览器记住这个值,并且每次访问服务器时,发送此值过来。可以从request内的Cookie值承载
演示
如下代码使用express.js,演示了一个访问计数的服务:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
var count = req.header("Cookie")
if (!count){
count = 0
}
count = parseInt(count) + 1
res.setHeader("Set-Cookie",count)
res.send('Your Visit page count:' + count)
})
app.get('/reset', (req, res) => {
res.setHeader("Set-Cookie",0)
res.send('Your Visit page count:' + 0)
})
app.listen(3000, () => console.log('Example app listening on port 3000!'))
可以打开浏览器,比如chrome,访问localhost:3000,每次刷新,可以看到:
Your Visit page count:0
的数字加1。
可以再打开另外一个和chrome不同的浏览器,比如safari,访问localhost:3000,每次刷新,可以看到:
Your Visit page count:0
的数字加1。这两个加1的动作,两个浏览器各自加各自的,互相并不影响。
创建 cookie
通过发送一个称为Set-Cookie的HTTP 消息头来创建一个 cookie,格式如下:
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
消息头的第一部分,value 部分,可以是任意字符串。但是通常是一个name=value格式的字符串。
可选项部分只会在浏览器端使用,而不会被发送至服务器端。包括过期时间选项,
过期时间选项
过期时间(expires),指定了 cookie 何时不会再被发送至服务器,随后浏览器将删除该 cookie。该选项的值是一个 Wdy, DD-Mon-YYYY HH:MM:SS GMT 日期格式的值
expires=Sat, 02 May 2009 23:38:25 GMT
如果 expires 设置了一个过去的时间点,那么这个 cookie 会被立即删掉。没有设置 expires 选项时,cookie 的生命周期仅限于当前会话中,关闭浏览器意味着这次会话的结束,
domain 选项
指定了 cookie 将要被发送至哪个或哪些域中。默认情况下,domain 会被设置为创建该 cookie 的页面所在的域名,所以当给相同域名发送请求时该 cookie 会被发送至服务器。例如,本博中 cookie 的默认值将是 bubkoo.com。domain 选项可用来扩充 cookie 可发送域的数量,Yahoo! 这种大型网站,都会有许多 *.yahoo.com 形式的站点(例如:my.yahoo.com, finance.yahoo.com 等等)。将一个 cookie 的 domain 选项设置为 yahoo.com,就可以将该 cookie 的值发送至所有这些站点。
path 选项
另一个控制 Cookie 消息头发送时机的选项是 path 选项,和 domain 选项类似,path 选项指定了请求的资源 URL 中必须存在指定的路径时,才会发送Cookie 消息头。这个比较通常是将 path 选项的值与请求的 URL 从头开始逐字符比较完成的。如果字符匹配,则发送 Cookie 消息头:
path=/blog
在这个例子中,path 选项值会与 /blog,/blogrool 等等相匹配;任何以 /blog 开头的选项都是合法的。
secure 选项
只有当一个请求通过 SSL 或 HTTPS 创建时,包含 secure 选项的 cookie 才能被发送至服务器。例如:
Set-Cookie: value; secure
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。