實用Nodejsnpm包:koa-csrf的示例分析

這篇文章將為大家詳細講解有關實用Nodejs npm包:koa-csrf的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

十余年品牌的成都網(wǎng)站建設公司,上1000家企業(yè)網(wǎng)站設計經(jīng)驗.價格合理,可準確把握網(wǎng)頁設計訴求.提供定制網(wǎng)站建設、購物商城網(wǎng)站建設、微信小程序定制開發(fā)、響應式網(wǎng)站建設等服務,我們設計的作品屢獲殊榮,是您值得信賴的專業(yè)網(wǎng)絡公司。

JS是什么

JS是JavaScript的簡稱,它是一種直譯式的腳本語言,其解釋器被稱為JavaScript引擎,是瀏覽器的一部分,主要用于web的開發(fā),可以給網(wǎng)站添加各種各樣的動態(tài)效果,讓網(wǎng)頁更加美觀。

koa-csrf是一個用于防止csrf攻擊的koa中間件。

當然關于什么是csrf、以及如何預防這里就不贅述了,有興趣的可以閱讀understanding-csrf。egg處理csrf方案。

首先我們看個簡單示例:

const router = require('koa-router')();
const CSRF = require('koa-csrf');
const csrfMD = new CSRF({
  invalidSessionSecretMessage: 'Invalid session secret',
  invalidTokenMessage: 'Invalid CSRF token',
  invalidTokenStatusCode: 403,
});

router
  .get('/',csrfMD,async (ctx, next) => {
    ctx.cookies.set('cid','1234', cookieSet);
    // 下發(fā)csrf token
    await ctx.render('index', {
      title: 'EJS !',
      csrf: ctx.csrf
    });
  })
  .post('/post', csrfMD ,async (ctx, next) => {
    console.log(ctx.method);
    ctx.session.email = ctx.request.body.email;
    ctx.session.name = ctx.request.body.name;
    ctx.redirect('/');
  })

module.exports = router;

簡單理解其工作流程:

客戶端請求頁面:

  • 服務端為用戶當前 session 生成 secret 值,并存到 session 里;

  • 根據(jù)secret生成csrf token,存到ctx._csrf;

  • 下發(fā)csrf token到客戶端

用戶寫操作,比如發(fā)送post 請求時:

  • 服務端獲取客戶端傳遞過來的csrf token;

  • 服務端從當前 session找到 secret 值;

  • 服務器用secret與接收的csrf token進行校驗;

koa-csrf

koa-csrf中關于token的創(chuàng)建、校驗邏輯都是在這個csrf包里。

const csrf = require('csrf');

class CSRF {
  constructor(opts = {}) {
    // opts配置對象、并且有提供默認配置
    // 允許自定義配置對象進行覆蓋
    this.opts = Object.assign(
      {
        // 使 koa 拋出的錯誤信息內(nèi)容,默認值為:'Invalid CSRF token'。
        // 它可以是一個接收 ctx 作為參數(shù)的函數(shù),函數(shù)最后返回錯誤信息內(nèi)容。
        invalidTokenMessage: 'Invalid CSRF token',
        // 驗證失敗時的響應狀態(tài)碼,默認值為:403(Forbidden)
        // 跟 invalidTokenMessage 參數(shù)一樣,它也會被傳遞給 ctx.throw,用于拋出錯誤和拒絕請求。
        invalidTokenStatusCode: 403,
        // 排除的請求方法,默認值為:['GET', 'HEAD', 'OPTIONS']。
        excludedMethods: ['GET', 'HEAD', 'OPTIONS'],
        // 是否禁止通過查詢字符串傳遞 _csrf 校驗 token,默認值為 false
        // 如果校驗 token 出現(xiàn)在 URL 中,則可能會通過 Referer 泄露,應盡量把 Token 放在表單中,把敏感操作由 GET 改為 POST。
        disableQuery: false
      },
      opts
    );

    // 生成token generation/verification instance
    this.tokens = csrf(opts);
    // 早期很多這樣的中間件寫法、對接koa中間件
    return this.middleware.bind(this);
  }

  // koa中間件
  middleware(ctx, next) {
    // __defineGetter__ API已經(jīng)不推薦使用
    // 在ctx上掛載csrf屬性。
    // 當讀取ctx.csrf會執(zhí)行該回調(diào)
    ctx.__defineGetter__('csrf', () => {
      // 如果已經(jīng)存在直接返回、避免多次生成
      if (ctx._csrf) {
        return ctx._csrf;
      }
      // csrf依賴于koa session
      if (!ctx.session) {
        return null;
      }

      // 生成一個secret存儲在ctx.session.secret
      if (!ctx.session.secret) {
        ctx.session.secret = this.tokens.secretSync();
      }
      // 根據(jù)上述的secret生成csrf toke存到ctx._csrf
      // 一般非框架本身屬性,都建議_xx表示私有
      ctx._csrf = this.tokens.create(ctx.session.secret);
      // 返回
      return ctx._csrf;
    });

    // 掛栽ctx.response.csrf屬性
    ctx.response.__defineGetter__('csrf', () => ctx.csrf);

    // 如果是請求方法黑名單直接不處理
    if (this.opts.excludedMethods.indexOf(ctx.method) !== -1) {
      return next();
    }

    if (!ctx.session.secret) {
      ctx.session.secret = this.tokens.secretSync();
    }

    // 從ctx.request.body取出客戶端傳遞過來的_csrf token
    // 因此依賴于koa-bodyparser類庫
    const bodyToken =
      ctx.request.body && typeof ctx.request.body._csrf === 'string'
        ? ctx.request.body._csrf
        : false;

    // 除了從body獲取token
    // 支持從ctx.query._csrf即get方法查詢字符串
    // 支持從請求頭獲取 'csrf-token'、'xsrf-token'、'x-csrf-token'、'x-xsrf-token'
    const token =
      bodyToken ||
      (!this.opts.disableQuery && ctx.query && ctx.query._csrf) ||
      ctx.get('csrf-token') ||
      ctx.get('xsrf-token') ||
      ctx.get('x-csrf-token') ||
      ctx.get('x-xsrf-token');

      // 如果獲取失敗、根據(jù)配置對象的信息、拋出異常
    if (!token) {
      return ctx.throw(
        this.opts.invalidTokenStatusCode,
        typeof this.opts.invalidTokenMessage === 'function'
          ? this.opts.invalidTokenMessage(ctx)
          : this.opts.invalidTokenMessage
      );
    }

    // 校驗token失敗
    if (!this.tokens.verify(ctx.session.secret, token)) {
      return ctx.throw(
        this.opts.invalidTokenStatusCode,
        typeof this.opts.invalidTokenMessage === 'function'
          ? this.opts.invalidTokenMessage(ctx)
          : this.opts.invalidTokenMessage
      );
    }
    // 校驗成功
    return next();
  }
}

module.exports = CSRF;

關于“實用Nodejs npm包:koa-csrf的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

文章名稱:實用Nodejsnpm包:koa-csrf的示例分析
當前網(wǎng)址:http://bm7419.com/article28/jcsgcp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站策劃、網(wǎng)站收錄App設計、App開發(fā)商城網(wǎng)站、網(wǎng)站維護

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設