客户端识别与 Cookie 机制

HTTP 最初是一个匿名、无状态的请求 / 响应协议。服务器处理来自客户端的请求,然后向客户端回送一条响应。Web 服务器几乎没有什么信息可以用来判定是哪个用户发送的请求,也无法记录来访用户的请求序列。

下表给出了七种最常见的用来承载用户相关信息的 HTTP 请求首部

首部名称 首部类型 描述
From 请求 用户的E-mail地址
User-Agent 请求 用户的浏览器软件
Referer 请求 用户是从这个页面上依照链接跳转过来的
Authorization 请求 用户名和密码
Client-IP 扩展(请求) 客户端的IP地址
X-Forwarded-For 扩展(请求) 客户端的IP地址
Cookie 扩展(请求) 服务器产生的ID标签

HTTP 基本认证

http内置了一种基本的认证方式,服务端对某次请求返回401,且响应头中包含WWW-Authenticate首部。

res.writeHead(401, {
  'WWW-Authenticate': 'Basic realm="only_english"'
})

此时,浏览器会弹出登录框


客户端识别与 Cookie 机制_第1张图片
在这里插入图片描述

输入完用户名和密码后,点击确定,浏览器会再次发送该请求,但是请求头首部中会携带Authorization首部。

Authorization: Basic YWRtaW46MTIzNDU2

YWRtaW46MTIzNDU2进行base64解码,可得admin:123456(正是我上面所输入的用户名admin,和密码123456

所以服务端程序应该判断请求头中有无Authorization首部,如果有的话,对其内容进行base64解码,获得用户名和密码,然后去和数据库数据进行匹配校验登录是否成功。

今后的请求要使用用户名和密码时,浏览器会自动将存储下来的值发送出去,甚至在站点没有要求发送的时候也经常会向其发送。浏览器在每次请求中都向服务器发送Authorization首部作为一种身份的标识,这样,只要登录一次,就可以在整个会话期间维持用户的身份了。

Cookie

可以笼统地将 cookie 分为两类:会话 cookie 和持久 cookie。会话cookie 是一种临时 cookie,它记录了用户访问站点时的设置和偏好。用户退出浏览器时,会话 cookie 就被删除了。持久 cookie 的生存时间更长一些;它们存储在硬盘上,浏览器退出,计算机重启时它们仍然存在。通常会用持久 cookie 维护某个用户会周期性访问的站点的配置文件或登录名。会话 cookie 和持久 cookie 之间唯一的区别就是它们的过期时间。稍后我们会看到,如果设置了Discard参数,或者没有设置ExpiresMax-Age参数来说明扩展的过期时间,这个 cookie 就是一个会话cookie。

cookie 就像服务器给用户贴的“嗨,我叫”的贴纸一样。用户访问一个Web 站点时,这个 Web 站点就可以读取那个服务器贴在用户身上的所有贴纸。
用户首次访问 Web 站点时,Web 服务器对用户一无所知。Web 服务器希望这个用户会再次回来,所以想给这个用户“拍上”一个独有的 cookie,这样以后它就可以识别出这个用户了。cookie中包含了一个由名字 = 值(name=value)这样的信息构成的任意列表,并通过Set-CookieSet-Cookie2HTTP 响应(扩展)首部将其贴到用户身上去。

语法:

Set-Cookie: name=value [; expires=date] [; path=path] [; domain=domain][; secure]
Cookie: name1=value1 [; name2=value2] ...
Set-Cookie属性 描述及实例
NAME=VALUE 强制的。
Expires 可选的。这个属性会指定一个日期字符串,用来定义cookie 的实际生存期。
日期的格式为:Weekday, DD-Mon-YY HH:MM:SS GMT。
唯一合法的时区为GMT,各日期元素之间的分隔符一定要是长划线。
如果没有指定Expires, cookie 就会在用户会话结束时过期。
Set-Cookie: foo=bar; expires=Wednesday, 09-Nov-99 23:12:40 GMT
Domain 可选的。浏览器只向指定域中的服务器主机名发送cookie。这样服务器就将 cookie 限制在了特定的域中。acme.com 域就与 anvil.acme.com 和 shipping.crate.acme.com 相匹配,但与www.cnn.com 就不匹配了。
Set-Cookie: SHIPPING=FEDEX; domain="joes-hardware.com"
Path 可选的。通过这个属性可以为服务器上特定的文档分配cookie。
如果没有指定路径,就将其设置为产生Set-Cookie响应的 URL 的路径,例如文档地址为/a/b,path为/a。文档地址为/a/b/c,path为/a/b。需要注意的是,/a/b/c除了可以获得/a/b下的cookie,也可以获得/a下的cookie。
Set-Cookie: lastorder=00183; path=/orders
Secure 可选的。如果包含了这一属性,就只有在 HTTP 使用 SSL 安全连接时才会发送 cookie:
Set-Cookie: private_id=519; secure

这里主要需要注意的是Cookie的domain属性(域属性),域属性直接指明了Cookie在什么域下可以使用,假如现在有两个域名:

account.test.com // 域名1
shop.test.com // 域名2

域名1域名2都是test.com的子域名,在域名1中,可以设置account.test.comtest.com的域下面的Cookie,同理,在域名2中,可以设置shop.test.comtest.com的域下面的Cookie。正因为如此,才可以实现单点登录,例如锤子科技在https://account.smartisan.com中登录后,你再去锤子论坛http://bbs.smartisan.com/时,登录态仍然存在,就是这个道理。

额外补充一点,设置Cookie时,如果显式地设置了domain属性,例如,test.com,浏览器存储时会自动在前面加.,变成.test.com存储,只有在没有设置domain属性的情况下,浏览器会默认加上当前的域名所在的域,且不会在头部加.,保证这个cookie只在当前域名下可用。

你可能感兴趣的:(客户端识别与 Cookie 机制)