Eggjs筆記:中間件配置、Post數據處理、安全機制CSRF防範、中間件模板全局變量配置

關於中間件

  • 中間件:匹配路由前、匹配路由完成做的一系列的操作
  • 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

    '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

    // add your middleware config here 加入中間件名
    config.middleware = [ 'printdatex' ];
    // 給中間件傳入參數
    config.printdatex = {
        aaa: 'aaa',
    };
    
  • 訪問頁面,可以看到輸出結果,配置完成

禁止ip請求的中間件配置

  • app/middleware下面新建forbidip.js 內容如下:

    '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

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

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中

<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

'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中配置

config.middleware = [ 'printdatex', 'forbidip', 'auth' ];

在app/controller/home.js去除csrf相關,view中的配置不變

async index() {
    const { ctx } = this;
    await ctx.render('index');
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章