Cookie
Cookie 是什么,Cookie 就是一串数据,而这串数据可以存在用户本地的终端上,从而起到辨别用户身份的作用。
背景
1993 年 3 月由网景公司前程序员卢·蒙特利发明,最开始定义于 RFC 2109, 而目前应用最广泛的标准是网景公司制定的标准上进行扩展后的版本
解决问题
HTTP 协议本身是个无状态的协议,如果单单只通过这个协议,那么对于服务端来说,用户上一次操作了啥它是不知道的,比如一个购物网站,用户买了点东西,到最后结帐时服务器不会知道用户买了什么,为了解决这个问题,Cookie 应运而生,即用户在买了点东西之后,服务器发送一段包含商品信息的 Cookie 给用户,这下用户在浏览其他网页时(或者在做其他的操作时)浏览器将这段 Cookie 发送回服务器,用户有买其他东西的时候在继续如上的操作,那么在结帐时服务器只需要那段用户(浏览器)返回的 Cookie 就行了,这样就知道了用户买了啥。
特点
- 服务器通过 Set-Cookie 响应头设置 Cookie
- 浏览器得到 Cookie 之后,每次请求都要带上 Cookie 发送给服务器
- 服务器读取 Cookie 就知道了用户的一些信息(登录信息、购物信息等)
其他一些 Cookie 相关
- 不同浏览器登录带上的 Cookie 是不一样的
- Cookie 可以被用户篡改,Session 可以解决这个问题
- Cookie 的默认有效期为 20 分钟左右,不同的浏览器策略不一样,后端可用 Set-Cookie 的 Max-Age 属性来强制设置有效期
- Cookie 遵守的同源策略跟 AJAX 的略有不同
比如
当请求 qq.com 下的资源时,浏览器会默认带上 qq.com 对应的 Cookie,不会带上 baidu.com 对应的 Cookie
当请求 v.qq.com 下的资源时,浏览器不仅会带上 v.qq.com 的Cookie,还会带上 qq.com 的 Cookie
另外,可以用过设置 Set-Cookie 的 Path 属性将 Cookie 与部分 Web 站点关联起来,起到一些限制作用 删除 cookie 的唯一方式
// 删除 Cookie 则指定 Set-Cookie 的 Expire 属性,指定一个已经过期的日期即可
document.cookie = 'fontSize=;expires=Thu, 01-Jan-1970 00:00:01 GMT';
// 这里 fontSize 为空,expires 为 1970 年的一个日期
注册和登录
注册逻辑
这里从最简单的情况开始说起,即一般来说,前端通过 POST 请求发送邮箱、密码、确认密码到后端,而后端通过解析 HTTP 请求的第四部分的信息得到前端发送的邮箱、密码、确认密码,然后会经历以下步骤
- 确认邮箱是否有效(当然这个也可以放到前端来做)
- 密码与确认密码是否一致(当然这个也可以放到前端来做)
- 检测邮箱对应用户是否已经注册(这里就要用到数据库的查询功能了),若存在则返回一个 400 状态码,若不存在就直接将信息录入数据库
登录逻辑
登录的逻辑也是差不多的,收到前端登录请求后,解析出主要的信息(邮箱、密码)、然后查询数据对比用户是否存在,用户存在则发送 Cookie 给前端并返回 200 OK,用户不存在则返回一个 401
一些细节
解析请求时需要监听这个请求传输过程中的 data 事件,为什么需要监听这个事件呢?因为当 http.createServer
的回调被调用的时候,也就是这个 server 接收到了所有的请求头的时候,但在这个时候也可能没有接收到请求中的 data 部分,所以这个时候就需要等待。当这段数据流发送过来时,就会触发 data
事件;当数据流都发送结束时,就会触发 end
事件。通过监听这两个事件来拿到请求中的 POST 上传的数据内容,代码如下function readBody(request){
return new Promise((resolve, reject)=>{
let body = []
// 监听 data 事件
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
// data 事件结束
// body 转码
body = Buffer.concat(body).toString();
resolve(body)
})
})
}
这段代码的逻辑是,先将那些一段一段的数据放到一个数据里面,然后用一个 Buffer
将这些数据连起来并最终返回一个大的 Buffer
,最后再将这段二进制数据变成字符串,然后通过 Promise 将数据结果传出去