关于中间件
- 中间件:匹配路由前、匹配路由完成做的一系列的操作
- Egg 是基于 Koa 实现的
- Egg 的中间件形式和 Koa 的中间件形式是一样的,都是基于洋葱圈模型
- Koa中的中间件:http://eggjs.org/zh-cn/intro/egg-and-koa.html#midlleware
- Egg中的中间件:http://eggjs.org/zh-cn/basics/middleware.html
- 一般来说中间件也会有自己的配置
- 在框架中,一个完整的中间件是包含了配置处理的
- 我们约定一个中间件是一个放置在 app/middleware 目录下的单独文件
- 它需要 exports 一个普通的 function,接受两个参数
- options: 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来
- app: 当前应用 Application 的实例
中间件测试
-
在中间件目录app/middleware中新建printdatex.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14'use strict';
/*
* options 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来
* app: 当前应用 Application 的实例
*/
module.exports = (options, app) => {
// 返回一个异步的方法
return async function printDate(ctx, next) {
console.log('md: ' + new Date());
console.log('opts: ' + options.aaa); // 打印options参数
await next();
};
}; -
在config中配置,打开app/config/config.default.js
1
2
3
4
5
6// add your middleware config here 加入中间件名
config.middleware = [ 'printdatex' ];
// 给中间件传入参数
config.printdatex = {
aaa: 'aaa',
}; -
访问页面,可以看到输出结果,配置完成
禁止ip请求的中间件配置
-
app/middleware下面新建forbidip.js 内容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32'use strict';
/*
* options 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来
* app: 当前应用 Application 的实例
*/
module.exports = (options, app) => {
// 返回一个异步的方法
return async function printDate(ctx, next) {
// 要屏蔽的ip从数据库获取, 要屏蔽的ip从参数传入 这两种方式
// 要屏蔽的ip
const forbidip = '127.0.0.1';
// 获取客户端的ip
// 本地访问 http://localhost:7001/ 这个ip打印的是 ::1 这个东西
// 本地访问 http://127.0.0.1:7002/ 打印的是正常的ip
// 也可以用自己电脑的ip来访问,正常输出
console.log('req ip: ' + ctx.request.ip);
// 仅作为演示
// 可以将ip地址写入配置读取数据库ip名单,这样异步操作
if (ctx.request.ip === forbidip) {
ctx.status = 403;
// ctx.message = 'your ip is forbidden!'; // 这个可以实现
// ctx.message = '禁止!'; // 这个有问题,不支持中文,特殊字符
ctx.body = '禁止访问!';
return;
}
await next();
};
}; -
加入config中配置,打开app/config/config.default.js
1 2 3 4 5 6 7 8 9 | config.middleware = [ 'printdatex', 'forbidip' ]; // 这个是配置演示,后续可以进行处理 config.forbidip = { ip: [ '127.0.0.1', '192.168.0.1' ], }; |
Post处理方式
- Egg 安全机制 CSRF 的防范:http://eggjs.org/zh-cn/core/security.html
- Egg Post 提交数据
1 ) 处理post请求的一种方式
在 app/controller/home.js
1 2 3 4 5 6 7 8 9 10 | async index() { const { ctx } = this; await ctx.render('index', { csrf: ctx.csrf }); } async add() { const { ctx } = this; // await ctx.render('index'); console.log(ctx.request.body); } |
在view/index.html中
1 2 3 4 5 | <form action="/add?_csrf=<%=csrf%>" method="POST"> 用户名: <input type="text" name="username" /> <br><br> 密 码: <input type="text" name="password" type="password" /> <button type="submit">提交</button> </form> |
这样便可接收到正确的请求信息,但是非常麻烦,页面多了,就有问题了
2 ) 使用中间件处理
编写 app/middleware/auth.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 'use strict'; /* * options 中间件的配置项,框架会将 app.config[${middlewareName}] 传递进来 * app: 当前应用 Application 的实例 */ module.exports = (options, app) => { // 返回一个异步的方法 return async function auth(ctx, next) { // 设置模板的全局变量 ctx.state.csrf = ctx.csrf; await next(); }; }; |
在config/config.default.js中配置
1 | config.middleware = [ 'printdatex', 'forbidip', 'auth' ]; |
在app/controller/home.js去除csrf相关,view中的配置不变
1 2 3 4 | async index() { const { ctx } = this; await ctx.render('index'); } |