Heim > Web-Frontend > js-Tutorial > Teilen Sie ein praktisches Nodejs npm-Paket: koa-csrf

Teilen Sie ein praktisches Nodejs npm-Paket: koa-csrf

青灯夜游
Freigeben: 2021-04-28 08:52:13
nach vorne
2781 Leute haben es durchsucht

In diesem Artikel stellen wir Ihnen ein praktisches Nodejs npm-Paket vor: koa-csrf. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

Teilen Sie ein praktisches Nodejs npm-Paket: koa-csrf

koa-csrf ist eine Koa-Middleware, die zur Verhinderung von CSRF-Angriffen verwendet wird.

Natürlich werde ich hier nicht näher darauf eingehen, was CSRF ist und wie man es verhindern kann. Wer sich dafür interessiert, kann understanding-csrf lesen. Egg kümmert sich um CSRF-Lösungen.

Zuerst schauen wir uns ein einfaches Beispiel an:

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);
    // 下发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;
Nach dem Login kopieren

Ein einfaches Verständnis seines Arbeitsablaufs:

Client-Anforderungsseite:

  • Der Server generiert einen geheimen Wert für die aktuelle Sitzung des Benutzers und speichert ihn in der Sitzung
  • Generiert Ein CSRF-Token basierend auf dem Geheimnis, speichern Sie es in ctx._csrf.
  • Senden Sie das CSRF-Token an den Client Client;
Der Server erhält das CSRF-Token aus der aktuellen Sitzung. Finden Sie den geheimen Wert.

Der Server verwendet das Geheimnis, um das empfangene CSRF-Token zu überprüfen.
  • koa-csrf-Token-Erstellung und -Verifizierung Logik sind alle in diesem
  • csrf
  • -Paket enthalten.
  • const csrf = require('csrf');
    
    class CSRF {
      constructor(opts = {}) {
        // opts配置对象、并且有提供默认配置
        // 允许自定义配置对象进行覆盖
        this.opts = Object.assign(
          {
            // 使 koa 抛出的错误信息内容,默认值为:'Invalid CSRF token'。
            // 它可以是一个接收 ctx 作为参数的函数,函数最后返回错误信息内容。
            invalidTokenMessage: 'Invalid CSRF token',
            // 验证失败时的响应状态码,默认值为:403(Forbidden)
            // 跟 invalidTokenMessage 参数一样,它也会被传递给 ctx.throw,用于抛出错误和拒绝请求。
            invalidTokenStatusCode: 403,
            // 排除的请求方法,默认值为:['GET', 'HEAD', 'OPTIONS']。
            excludedMethods: ['GET', 'HEAD', 'OPTIONS'],
            // 是否禁止通过查询字符串传递 _csrf 校验 token,默认值为 false
            // 如果校验 token 出现在 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已经不推荐使用
        // 在ctx上挂载csrf属性。
        // 当读取ctx.csrf会执行该回调
        ctx.__defineGetter__('csrf', () => {
          // 如果已经存在直接返回、避免多次生成
          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();
          }
          // 根据上述的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');
    
          // 如果获取失败、根据配置对象的信息、抛出异常
        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;
    Nach dem Login kopieren
    In der nächsten Ausgabe werfen wir einen Blick auf die CSRF-Bibliothek, die weitere verwandte Logik verwaltet.

    Okay, das war's für heute, bis zum nächsten Mal.

    ps: Wenn Sie auch an Node interessiert sind, folgen Sie bitte meinem offiziellen Konto: xyz Programming Diary.

    Verwandte Empfehlungen: „nodejs-Tutorial

    Das obige ist der detaillierte Inhalt vonTeilen Sie ein praktisches Nodejs npm-Paket: koa-csrf. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage