Node学习入门篇(七):Connect自带的中间件

本章内容

  • 解析cookie、请求主体和查询字符串的中间件
  • 实现Web程序核心功能的中间件
  • 处理Web程序安全的中间件
  • 提供静态文件服务的中间件

npm package: https://www.npmjs.com/package/package

解析cookie、请求主体和查询字符串的中间件

  • 常用中间件
    这里写图片描述

    这里写图片描述

注意:All node patches will be removed - all middleware should work without Connect and with similar frameworks like restify(connect内置中间件已经从connect中分离处理,使用时需要单独安装、引入)

  • 未签名cookie

1) install

npm install cookie-parser

2) 常规(未签名)cookie测试

var connect = require('connect');
var app = connect();
var cookieParser = require('cookie-parser')
app.use(cookieParser('sysuygm is cool'));
app.use(function(req, res) {
    console.log(req.cookies);
    console.log(req.signedCookies);
        "cookie":req.cookies,
        "signedCookies":req.signedCookies
        }));
});

3)客户端结果

发送

accept: application/json
accept-encoding: gzip, deflate
accept-language: en-US,en;q=0.8
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Authorization: Basic ZmFmYTpmYWZh
Cookie: foo=bar;bar=baz

收到

{
"cookie": {
"foo": "bar",
"bar": "baz",
"io": "GXHOFF8zxkVibldwAAAO"
},
"signedCookies": {}
}
  • 签名cookie

签名cookie更适合敏感数据,因为用它可以验证cookie数据的完整性,有助于防止中间人攻击。有效的签名cookie放在req.signedCookies对象中。把两个对象分开是为了体现开发者的意图。如果把签名的和未签名的cookie放到同一个对象中,常规cookie可能就会被改造,仿冒签名的cookie

签名cookie看起来像tobi.DDm3AcVxE9oneYnbmpqxoyhyKsk一样,点号(.)左边的是cookie的值,右边是在服务器上用SHA-1 HMAC生成的加密哈希值(基于哈希的消息认证码)。如果cookie的值或者HMAC被改变的话,Connect的解签会失败

扫描二维码关注公众号,回复: 1467635 查看本文章

1) 使用签名的cookie

cookieParser()中间件没有提供任何通过Set-Cookie响应头向HTTP客户端写出站cookie的功能。但Connect可以通过res.setHeader()函数写入多个Set-Cookie响应头

app.use(function(req, res) {
    console.log(req.cookies);
    // console.log(req.signedCookies);
    res.setHeader('Set-Cookie',
    'foo-bar;Expires=True,08 Jun 2021 10:18 GMT');
    res.end(JSON.stringify( {'seccuss':true}));
});

2) curl 查看

>curl http://localhost:3000/ -H "Cookie:foo-bar" --head
HTTP/1.1 200 OK
Content-Type: application/json
Set-Cookie: foo-bar;Expires=True,08 Jun 2021 10:18 GMT
Date: Sun, 15 Apr 2018 15:16:58 GMT
Connection: keep-alive

bodyParser():解析请求主体

  • 假设你要用HTML标签接受用户上传的文件。用一行代码添加bodyParser()中间件就全齐了
  • bodyParser()组件为你提供了req.body属性,可以用来解析JSON、x-www-form-urlencoded和multipart/form-data请求
  • 如果是multipart/form-data请求,比如文件上传,则还有req.files 对象
  • 这是个非常有用的组件,实际上它整合了其他三个更小的组件:json(), urlencoded(), 和multipart()

1) 先安装

npm install body-parser

2) 使用

var cookieParser = require('cookie-parser')
// app.use(bodyParser()); 最好是像下面那样显示指定子组件,否则会提示冗余

// parse application/x-www-form-urlencoded
 app.use(bodyParser.urlencoded({ extended: false }));

// parse application/json
 app.use(bodyParser.json());

app.use(function(req, res) {
    console.log(req.body.username);
    // console.log(req.signedCookies);
    res.end(JSON.stringify( {
        'username':req.username,
        'password':req.pass
    }));
});

POST数据

{
  "username": "caicai",
  "pass":"sysuygm"
}

如果bodyParser()在内存中缓存json和x-www-form-urlencoded请求主体,产生一个大字符串,那攻击者会不会做一个超级大的JSON请求主体对服务器做拒绝服务攻击呢?答案基本上是肯定的,所以Connect提供了limit()中间件组件。

limit():请求主体的限制

  • limit()中间件组件的目的是帮助过滤巨型的请求
  • 防止脚本攻击
    (好像已经被丢弃了)

query():查询字符串解析

  • 它解析查询字符串,为程序提供req.query对象
  • 它会将请求发送过来的查询字符串以JSON格式作为响应返回去
    (似乎已经被废弃?)

favicon():提供favicon

(似乎已经被废弃?)
使用 serve-favicon代替,用static-favicon会提示:

(node:3324) 
DeprecationWarning: static-icon deprecated; switch to module serve-favicon

使用firefox才能看到favicon!

::1 - - [Sun, 15 Apr 2018 16:55:37 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
undefined
::1 - - [Sun, 15 Apr 2018 16:59:42 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"
undefined
::1 - - [Sun, 15 Apr 2018 16:59:54 GMT] "GET / HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"

logger():记录请求

已被废弃,现在用morgan代替, 直接安装morgan

body-parser deprecated bodyParser: use individual json/urlencoded middlewares connect.js:27:9
body-parser deprecated undefined extended: provide extended option ..\node_modules\body-parser\index.js:105:29
morgan deprecated undefined format: specify a format connect.js:30:9
morgan deprecated default format: use combined format connect.js:30:9
listening...
undefined
::1 - fafa [Sun, 15 Apr 2018 16:48:14 GMT] "POST /?username=pppp HTTP/1.1" 200 - "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"

vhost():虚拟主机

  • vhost()(虚拟主机)中间件是一种通过请求头Host路由请求的简单、轻量的办法
  • 这项任务通常是由反向代理完成的,可以把请求转发到运行在不同端口上的本地服务器那里
  • vhost()组件在同一个Node进程中完成这一操作,它将控制权交给跟vhost实例关联的Node HTTP服务器
  • 可使子域名在Express中更容易管理。
  • 缺点:如果一个网站引发了崩溃,你的所有网站都会宕掉(因为它们都运行在同一个进程中)

session():会话管理

需要安装 session-parser,且在cookie-parser前引入。


安全相关部分

basicAuth():HTTP基本认证

  • 基本认证是非常简单的HTTP认证机制,并且在使用时应该小心,因为如果不是通过HTTPS进行认证,用户凭证很可能会被攻击者截获

  • basicAuth()在最新的connect中已无法使用,且无法单独使用,似乎只有Express中才能使用。

app.use(basicAuth(connect.basicAuth(auth)));
                          ^

TypeError: connect.basicAuth is not a function
    at Object.<anonymous> (F:\后台开发\wechat\lib\connect.js:30:27)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3

csrf():跨站请求伪造防护

  • 跨站请求伪造(CSRF)利用站点对浏览器的信任漏洞进行攻击
  • csrf()会生成一个包含24个字符的唯一ID,认证令牌,作为req.session._csrf附到用户的会话上
  • 这个令牌会作为隐藏的输入控件_csrf出现在表单中,CSRF在提交时会验证这个令牌
>npm install csrf

使用:
为了确保csrf()可以访问req.body._csrf(隐藏输入控件的值)和req.session._csrf,你要确保csrf()添加在了bodyParser()和session()的下面

app.use(favicon(__dirname + '/timg.ico'));
// app.use(basicAuth(connect.basicAuth(auth)));
app.use(cookieParser('private-key'));
app.use(session({
    keys:['aaa','bbb','ccc'],
    maxAge:360000*24,
    name:'session'
}));
app.use(bodyParser());
//添加在bodyParser()和session()的下面
app.use(csrf());
app.use(morgan());

errorHandler():开发错误处理

  • 可以基于请求头域Accept提供详尽的HTML、JSON和普通文本错误响应
  • errorHandler()是要用在开发过程中的,不应该出现在生产环境中

安装:

npm install errorhandler

example:

var connect = require('connect')
var errorhandler = require('errorhandler')

var app = connect()

if (process.env.NODE_ENV === 'development') {
  // only use in development 
  app.use(errorhandler())
}

static():静态文件服务

  • static()中间件实现了一个高性能的、灵活的、功能丰富的静态文件服务器,支持HTTP缓存机制、范围请
  • 有对恶意路径的安全检查,默认不允许访问隐藏文件(文件名以.开头),会拒绝有害的null字节
  • static()本质上是一个非常安全的、完全能胜任的静态文件服务中间件,可以保证跟目前各种HTTP客户端的兼容
  • 假定你的程序遵循典型的场景,要返回./public目录下的静态资源文件

compress():压缩静态文件

directory():目录列表

猜你喜欢

转载自blog.csdn.net/w_bu_neng_ku/article/details/79955622