Node实战篇:Express 中间件 cookie-parser(六)

逃离Java 2018-04-02 15:25:57 ⋅ 669 阅读

第一部分 cookie

首先了解一下会话

会话是一种持久的网络协议,用于完成服务器和客户端之间的一些交互行为。会话是一个比连接粒度更大的概念,一次会话可能包含多次连接,每次连接都被认为是会话的一次操作。

Cookie是由网景公司的前雇员Lou Montulli在1993年发明的,在RFC2109(已废弃,被RFC2965取代)里初次被描述的,每个客户端最多保持三百个cookie,每个域名下最多20个Cookie(实际上一般浏览器现在都比这个多,如Firefox是50个),而每个cookie的大小为最多4K,不过不同的浏览器都有各自的实现。对于cookie的使用,最重要的就是要控制cookie的大小,不要放入无用的信息,也不要放入过多信息。

1.1 cookie概述


HTTP 是一个无状态协议,所以客户端每次发出请求时,下一次请求无法得知上一次请求所包含的状态数据;
Cookie是解决HTTP无状态性的有效手段,服务器可以设置或读取Cookie中所包含的信息。
简单的说,cookie是服务器发给用户的一个标识,用来帮助服务器识别用户,从而记录用户状态。

1. 用户第一次访问网站时,服务器向客户端发送 cookie。通常使用 HTTP 协议规定的 set-cookie 头操作。规范规定 cookie 的格式为 name = value 格式,且必须包含这部分。
2. 浏览器将 cookie 保存。
3. 每次请求浏览器都会将 cookie 发向服务器。

cookie 其他参数option:

1. path:表示 cookie 影响到的路径,匹配该路径才发送这个 cookie。
2. expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。一般用来保存 session 的 session_id。
3. secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
4. httpOnly:浏览器不允许脚本操作 document.cookie 去更改 cookie。一般情况下都应该设置这个为 true,这样可以避免被 xss 攻击拿到 cookie。
1.2 Cookie分类
1. 内存式Cookie: 存储在内存中,浏览器关闭后就会消失;
2. 硬盘式Cookie: 保存在硬盘中,其不会随浏览器的关闭而消失,除非用户手工清理或到了过期时间。
1.3 Cookie 的安全隐患

Cookie提供了一种手段使得HTTP请求可以附加当前状态, 现今的网站也是靠Cookie来标识用户的登录状态的:

  1. 用户提交用户名和密码的表单,这通常是一个POST HTTP请求。

  2. 服务器验证用户名与密码,如果合法则返回200(OK)并设置Set-Cookie为authed=true。

  3. 浏览器存储该Cookie。

  4. 浏览器发送请求时,设置Cookie字段为authed=true。

  5. 服务器收到第二次请求,从Cookie字段得知该用户已经登录。 按照已登录用户的权限来处理此次请求。



    这里面的问题在哪里?

假如我们直接设置Cookie字段为authed=true并发送该HTTP请求, 服务器岂不是被欺骗了?这种攻击非常容易,Cookie是可以被篡改的!

1.4 Cookie 防篡改机制

服务器可以为每个Cookie项生成签名,由于用户篡改Cookie后无法生成对应的签名, 服务器便可以得知用户对Cookie进行了篡改。

1. 在服务器中配置一个不为人知的字符串(我们叫它Secret),比如:x$sfz32。
2. 当服务器需要设置Cookie时(比如authed=false),不仅设置authed的值为false, 在值的后面进一步设置一个签名,最终设置的Cookie是authed=false|6hTiBl7lVpd1P。 3. 签名6hTiBl7lVpd1P是这样生成的:Hash('x$sfz32'+'true')。 要设置的值与Secret相加再取哈希。 4. 用户收到HTTP响应并发现头字段Set-Cookie: authed=false|6hTiBl7lVpd1P。
5. 用户在发送HTTP请求时,篡改了authed值,设置头字段Cookie: authed=true|???。 因为用户不知道Secret,无法生成签名,只能随便填一个。 6. 服务器收到HTTP请求,发现Cookie: authed=true|???。服务器开始进行校验: Hash('true'+'x$sfz32'),便会发现用户提供的签名不正确。

第二部分: cookie-parser

实例代码(不签名形式):

var express = require('express');
// 首先引入 cookie-parser 这个模块var cookieParser = require('cookie-parser');
var app = express(); app.listen(3000);
//不采用签名形式app.use(cookieParser());
// 如果请求中的 cookie 存在 bwf, 则输出 cookie// 否则,设置 cookie 字段 bwf, 并设置过期时间为1分钟
app.get('/', function (req, res) {  
//不采用签名形式获取cookie的方法:  req.cookies.  if (req.cookies.bwf) {    
   console.log(req.cookies);    res.send("再次欢迎访问");  } else {    
       //name value 过期时间       res.cookie('bwf', '1234', {maxAge: 6 * 1000, path: '/'});           res.send("欢迎第一次访问");  } });

chrome中cookie显示为name=value


2.2 cookie-parser API

cookie-Parser和 express-session 这两个中间件在express 4版本之后解耦了,最开始如果用express-session 的话一定也要用cookieParser,

中间件包含三个模块:cookie cookie-praser cookie-signature.;
其中,cookie cookie-signature这两个模块是private的。所有的public API都在cookie-Parser中。
cookie-Parser 有四个接口;

module.exports = cookieParser;module.exports.JSONCookie = JSONCookie;module.exports.JSONCookies = JSONCookies;module.exports.signedCookie = signedCookie;module.exports.signedCookies = signedCookies;
req.secret:传入的秘钥用于对cookie进行加密req.cookies:对req.headers.cookie中的cookie进行解析,返回的一个对象req.signedCookies:保存的是解析后的cookie的真实值,但是可能还会被JSONCookie进行处理

2.2.1 cookieParser(secret, options) 返回的是一个中间件函数

1. secret(可选): 可以用string 或是 array 来签名cookie;默认无
2. options: 第一部分中cookie的可选对象;

2.2.2 cookieParser.JSONCookie(str)
将cookie作为json格式解析, 如果是json格式的value,就返回, 否则返回过去式;

2.2.3 cookieParser.JSONCookies(cookies)
给定一个对象,会重复调用cookieParser.JSONCookie

2.2.4 cookieParser.signedCookie(str, secret)
解析签名cookie,

2.2.5 cookieParser.signedCookies(cookies, secret)
给定一个对象, 重复调用cookieParser.signedCookie(str, secret)

实例代码(签名):

信息可见不可篡改

var express = require('express');
// 首先引入 cookie-parser 这个模块
var cookieParser = require('cookie-parser');var app = express();
/*--------------采用签名方式--------------*/

//第一步 设置签名 string
app.use(cookieParser('singedMyCookie')); app.get('/', function (req, res) {  
if (req.signedCookies.bwf) {
//第三步: 使用signedCookies获取cookie (采用签名形式获取cookie的方法:  req.signedCookies.    console.log(req.signedCookies);    res.send("再次欢迎访问");  } else {
   //第二步: 设置{signed: true}    res.cookie("bwf", "hhw", {signed: true});    res.send("欢迎第一次访问");  } }); app.listen(3000);

chrome中cookie显示为bwf=s%3......... 签名前是bwf=hhw



关注我们

如果需要源码可以关注“IT实战联盟”公众号并留言(源码名称+邮箱),小萌看到后会联系作者发送到邮箱,也可以加入交流群和作者互撩哦~~~!



全部评论: 0

    我有话说:

    Node实战Express 中间-body-parser(五)

    body-parser是什么?body-parser是一个HTTP请求体解析中间,使用这个模块可以解析JS

    Node实战Express中间与request(四)

    Express 是一个路由和中间 Web 框架,其自身只具有最低程度的功能:Express 应用程序基本上是一系列中间函数调用。

    Node实战Express路由(三)

    Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。

    Node实战Express-session解析(八)

    Session和HTTP协议属于不同层面的事物,HTTP属于ISO七层模型的最高层应用层,前者Session不属于后者,前者HTTP是具体的动态页面技术来实现的,但同时它又是基于后者的。

    Node实战Express--jade模板引擎(七)

    Jade(Pug) — Node Template Engine,一个高性能的模板引擎,专为 Node 而做......

    Node实战:阶段项目(九)

    项目整体预览 项目的github地址 界面逼格还行-_- 主要功能: 登陆; 退出; 所用的主要模块: express, 路由.静态文件.模块分工等; express-session, 采用

    Node.js 实战--微信支付系列(二)

    接上一首先我们看一下整体上微信小程序的开发流程图

    Node模块之fs模块()

    屏幕快照 2017-08-08 上午10.53.21.png 第一部分 概述 Node.js 提供一组类似UNIX(POSIX)标准的文件操作API,Node.js中操作文件的模块是fs(File

    Node实战Nodejs 链接 Mariadb 实例

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL

    Express系列---路由(二)

    Express 是一个自身功能极简,完全是由路由和中间构成一个的开发框架。

    Node实战:使用joi来验证数据模型 (十)

    Joi 是 hapijs 自带的数据校验模块,他已经高度封装常用的校验功能,本文就是介绍如何优雅地使用 joi 对数据进行校验......

    Node.js 实战--微信支付系列(一)

    真正的无知不是知识的贫乏, 而是拒绝获取知识!——波普尔 (哲学家 思想家)鉴于微信支付文档内容详实

    Node&RabbitMQ系列 保证消费

        上文章主要以生产者角度:确保消息发出去了,这文章主要以消费者的角度:确保处理了对应的消息 Quonum Queue不适用场景适用场景代码实现RePublish

    Node模块之Events模块(五)

    Node模块之Events模块(五)

    Node 模块之 util URL queryString path(八)

    第一部分 util util是一个Node.js核心模块,util模块设计的主要目的是为了满足Node内部API的需求。其中包括:格式化字符串、对象的序列化、实现对象继承等常用方法。要使用util

    NodeJS 10.5.0 中的线程:实用介绍

    几天前,Node.js版本10.5.0发布,其中包含的主要功能之一是添加了线程支持。

    Nodejs视频服务器 切片ffmpeg

    Node 视频服务器 切片ffmpeg

    Kafka 慌了!这个中间,要火了?

    你知道吗?在消息中间的编年史上,RocketMQ可谓独当一面。作为Apache 顶级项目(TLP),Apache RocketMQ 是国内首个非 Hadoop 生态体系的顶级项目,开源至今被全球