为了账号安全,请及时绑定邮箱和手机立即绑定

《Node与Express开发》学习笔记-第九章 Cookie与会话

标签:
Node.js

HTTP是无状态协议。这就是说,当你在浏览器中加载页面,然后转到同一网站的另一页面时,服务器和浏览器都没有任何内在的方法可以认识到,这是同一浏览器访问同一网站。换一种说法,Web工作的方式就是在每个HTTP 请求中都要包含所有必要的信息,服务器才能满足这个请求。

会话的作用就是让浏览器与服务器之间能够有一个记录状态的地方。浏览器可以操作这个记录状态的地方服务器也可以。这样服务器就能够识别出不同的浏览器,和浏览器不同的状态。

什么是cookie

cookie 的想法很简单:服务器发送一点信息,浏览器在一段可配置的时期内保存它。发送哪些信息确实是由服务器来决定:通常只是一个唯一ID号,标识特定浏览器,从而维持一个有状态的假象。

在这里最用的会话就是cookie,但是cookie还有许多缺点。虽然html5中也加入和其他的会话机制,但是不见得老版本IE能够支持。所以还是要学习一下cookie,先了解他的缺点开始把。

  • cookie对用户来说不是加密的
    服务器向客户端发送的所有cookie都能被客户端查看。你可以向客户端发送一些加密过的信息以保护其中的内容,但几乎不会有这种需求(至少在你不做坏事时是这样的)。我们会稍微讨论一下签名cookie,它可以混淆cookie中的内容,但对于窥探者来说这Cookie与会话绝没有加密那样的安全性。
  • 用户可以删除或禁用cookie
    用户对cookie有绝对的控制权,并且浏览器支持批量或单个删除cookie。除非你图谋不轨,否则用户没理由去删它,但在测试过程中有这种需求。用户也可以禁用cookie,但这更容易造成问题,因为只有最简单的Web应用程序才不需要依赖cookie。
  • 一般的cookie可以被篡改
    不管浏览器什么时候发起一个跟cookie关联的请求,只要你盲目地相信cookie中的内容,都有可能会受到攻击。比如说,有些极其愚蠢的人会执行cookie中的代码。要确保cookie不被篡改,请使用签名cookie。
  • cookie可以用于攻击
    这几年出现了一种叫作跨站脚本攻击 (XSS)的攻击方式。XSS 攻击中有一种技术就涉及用恶意的JavaScript修改cookie中的内容。所以不要轻易相信返回到你的服务器的cookie 内容。用签名cookie会有帮助(不管是用户修改的还是恶意JavaScript修改的,这些篡改都会在签名cookie中留下明显的痕迹),并且还可以设定选项指明cookie 只能由服务器修改。这些cookie的用途会受限,但它们肯定更安全。
  • 如果你滥用cookie,用户会注意到
    如果你在用户的电脑上设了很多cookie,或者存了很多数据,这可能会惹恼用户,所以你应该避免出现这种情况。尽量把对cookie 的使用限制在最小范围内。
  • 如果可以选择,会话要优于cookie
    大多数情况下,你可以用会话维持状态,一般来说这样做是明智的。并且会话更容易,你不用担心会滥用用户的存储,而且也更安全。当然,会话要依赖cookie,但如果你使用会话,Express会帮你做很多工作。

通俗的说:

  1. cookie可以通过一些特殊的方式读取并修改,可以通过加密cookie来加强信息保护(这里可以使用md5加密,JS有相关这方面的库)。
  2. 不涉及到用户安全信息的地方用用cookie是没什么问题的,但是涉及的安全的地方就需要用其他方法了(例如:session)。
  3. cookie能够长期保存信息,再次访问页面的时候可以保持上次访问时的状态。
9.1 凭证的外化
cookie 秘钥

cookie 秘钥是一个字符串,服务器知道它是什么,它会在cookie 发送到客户端之前对cookie加密。这是一个不需要记住的密码,所以可以是随机字符串。我一般用一个随机密码生成器(受xkcd启发,http://preshing.com/20110811/xkcd-password-generator)来生成cookie 秘钥。

这里作者没有讲太清楚,我猜测可能是通过在浏览器保存一个随机的秘钥,服务器同时也在针对这个账户保持这个秘钥。 浏览器发送过来的cookie后服务器这个账户和秘钥是否匹配从而达到凭证的效果。

外化第三方凭证

其他的凭证
数据库密码
API 令牌(Twitter、Facebook 等)。

作者这里用了一个简单的方式做了个cookie 秘钥
创建cookie 秘钥模块 credentials.js

module.exports = {
    cookieSecret: ' 把你的cookie 秘钥放在这里',
};

在入口文件引入

var credentials = require('./credentials.js');
9.2 Express中的Cookie

Exrpess需要推过中间件来解析cookie

npm install --save cookie-parser

引入中间件

app.use(require('cookie-parser')(credentials.cookieSecret));

看来还是有必要详细阅读一下cookie-parser文档

cookie基本用法

设置cookie
cookie是通过浏览器请求发送过来了。服务器又是通过路由来处理请求的。所以cookie的处理就是在路由的请求和响应对象中。

res.cookie一般就是设置cookie 了。 因为cookie是保持在浏览器中的,所以服务器通过res把cookie的设置信息发送给浏览器,浏览器再去修改cookie。

res.cookie('monster', 'nom nom');  // 普通cookie
res.cookie('signed_monster', 'nom nom', { signed: true }); // 签名cookie

签名cookie 的优先级高于未签名cookie。如果你将签名cookie 命名为signed_monster,那就不能用这个名字再命名未签名cookie(它返回时会变成undefined)。

访问cookie

访问cookie当然就是需要从浏览器请求来访问了。

var monster = req.cookies.monster;
var signedMonster = req.signedCookies.monster;

任何字符串都可以作为cookie 的名称。比如,我们可以用'signed monster'代替'signed_monster',但这样我们必须用括号才能取到cookie:req.signedCookies['signed monster']。因此我建议不要在cookie 的名称中使用特殊字符。

删除cookie
res.clearCookie('monster');

cookie高级用法

设置cookie 时可以使用如下这些选项:

  • domain
    控制跟cookie 关联的域名。这样你可以将cookie分配给特定的子域名。注意,你不能给cookie设置跟服务器所用域名不同的域名,因为那样它什么也不会做。
  • path
    控制应用这个cookie的路径。注意,路径会隐含地通配其后的路径。如果你用的路径是/(默认值),它会应用到网站的所有页面上。如果你用的路径是/foo,它会应用到/foo、/foo/bar等路径上。
  • maxAge
    指定客户端应该保存cookie多长时间,单位是毫秒。如果你省略了这一选项,浏览器关闭时cookie就会被删掉。(你也可以用expiration 指定cookie过期的日期,但语法很麻烦。我建议用maxAge。)
  • secure
    指定该cookie 只通过安全(HTTPS)连接发送。
  • httpOnly
    将这个选项设为true 表明这个cookie 只能由服务器修改。也就是说客户端JavaScript不能修改它。这有助于防范XSS攻击。
  • signed
    设为true 会对这个cookie 签名,这样就需要用res.signedCookies而不是res.cookies访问它。被篡改的签名cookie 会被服务器拒绝,并且cookie 值会重置为它的原始值。

(高级部分的具体使用方法后续更新)

9.3 检查Cookie

在这里就可以查看Cookie信息了。
图片描述
这里还有Local Storage,看看慕课把文章缓存到了我们浏览器的Local Storage下。
浏览器对cookie有些限制,例如cookie一般只有2k-4k大小。
cookie的信息条数也最多也就30-50条。所以使用的时候还是需要注意一下的。

拓展阅读:
各浏览器Cookie大小、个数限制
http://www.cnblogs.com/henryhappier/archive/2011/03/03/1969564.html
9.4 会话
9.4.1 内存存储(session)

session与cookie的区别在于,session是放置在服务器端内存了。这样有个好处就是安全,浏览器是不能串改session。但是也有很多缺点:
重启服务器后数据就会丢失(这也就是内存的特性),如果拓展多台服务器每个服务器的内存是独立的。那么每次请求可能是由不同的服务器处理的的,所以会话数据有时在那里,有时不在。这明显是不可接受的用户体验。
小项目用用就可以了,大项目就可以考虑使用永久地存储会话信息(和数据库有关)。

安装express-session中间件

npm install --save express-session

然后, 在链入cookie-parser 之后链入express-session:

app.use(require('cookie-parser')(credentials.cookieSecret));
app.use(require('express-session')());

使用session
中间件express-session 接受带有如下选项的配置对象:

  • key
    存放唯一会话标识的cookie 名称。默认为connect.sid。
  • store
    会话存储的实例。默认为一个MemoryStore 的实例,可以满足我们当前的要求。第13章将会介绍如何使用数据库存储。
  • cookie
    会话 cookie 的 cookie设置( path、domain、secure 等)。适用于常规的 cookie默认值。

通俗的说:
key:
当浏览器与服务器建立链接的时候服务器就会在session中创建一个Key值用于区分不同的端浏览器。
store:
貌似是session通过内存存储的信息的地方。 可以通过数据库存储代替。
cookie
貌似是讲可以通过他访问cookie的一些值。

操作session
对于会话而言,我们不是用请求对象获取值,用响应对象设置值,它全都是在请求对象上操作的。

req.session.userName = 'Anonymous';
var colorScheme = req.session.colorScheme || 'dark';
req.session.userName = null; // 这会将'userName' 设为null 但不会移除它
delete req.session.colorScheme; // 这会移除'colorScheme'
总结:

这章学习了如何使用cookie和session进行会话。
从项目角度来考虑就是如何通过会话让服务器去区别不同来源的浏览器端,然后进行分别处理。还有就是可以保持浏览状态一般为跨页浏览提供了公共信息的存放位子。

自己的感受:
越发觉得作者的特点是那种点到为止型的。只要理解了原理剩下的就是需要填充就可以了。这样的好处也有助于能够快速上手一个项目。对于前端想了解后端的同学真是一本不错的书。
有些细节部分和实例部分我没有写的很具体,推荐大家阅读一下原文。

点击查看更多内容
8人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消