2016-02-12 78 views
3

对不起,我不太了解koa的秘密钥匙工程。在兴亚,有 上app对象keys场,这将是这样使用:为什么koa上需要多个密钥?

const app = new Koa(); 
app.keys = ['some secret', 'another secret', 'or more ...']; // it's an 
                  // array right? 

,然后使用koa-csrf中间件时,默认情况下内置csrf.middleware不使用由app.keys提供的密钥。如果我使用默认中间件 ,则需要创建另一个中间件,以便在会话上设置密钥 。

app.use(session()); // koa-generic-session 
app.use(async (ctx, next) => {    // without this custom middleware 
    ctx.session.secret = 'yet another secret'; // POST /protected-route 
    await next();        // will give 403 
});           // missing secret 
csrf(app); 
app.use(csrf.middleware); 

当我使用瓶,我需要提供只有一个密钥是由 不stringarray设置。为什么需要多个密钥?整个应用程序仅使用一个还不够?

回答

3

好像你在这里问了很多事情。

  1. 您可以为密钥旋转的目的提供Koa app.keys = [...]多个密钥。

    例如,如果您想要每月生成一个新密钥,则可以使用它签署新的cookie,而不要立即使所有旧的cookie无效。相反,您宁愿让旧的Cookie自然过期。

    如果你不关心按键旋转,那么你只需要使用你永远不会改变的app.keys = ['mysecret']

  2. koa-csrf的中间件实际上使用您用app.keys=设置的密钥。

    兴亚通过app.keys到其饼干实例(https://github.com/pillarjs/cookies),使得内置this.cookies.get()this.cookies.set()将使用键(如果有的话)。

    koa-session使用Koa的内置this.cookies.{get,set}

    koa-csrf使用koa-session

但所有这些都是无关紧要的。

403响应并非抱怨你没有设置app.keys=秘密。这是抱怨你没有提供CSRF令牌(又名秘密),而不是一个有效的令牌。

手动设置this.session.secret的“修复”只是手动设置koa-csrf寻找CSRF标记的值。您绕过了CSRF系统的整个安全措施。

CSRF令牌系统的重点在于确保有人碰到受保护的端点实际上源自例如<form>,该端点从您控制的页面发布到该端点。

它通过生成一个令牌,将其保存在cookie中,将令牌附加到窗体上,然后在提交时确保窗体令牌与会话令牌相匹配。

你似乎缺少什么,你必须:

  1. 生成它的CSRF令牌
  2. 设置到secret cookie的客户端
  3. 揭露CSRF令牌传递给客户端,以便他们将它提交给您的受保护端点。
  4. 在受保护的端点上,确保客户端发送与其“秘密”cookie中的CSRF令牌相匹配的CSRF令牌。 Here are the places即 koa-csrf检查以找到该令牌。

koa-csrf's this.csrf呼叫#1和#2。你必须实现#3。 koa-csrf's this.assertCSRF确实#4。

所以,都在一起,这是它的外观(未经测试):

var koa = require('koa') 
var csrf = require('koa-csrf') 
var session = require('koa-session') 
var Router = require('koa-router'); 
var bodyParser = require('koa-bodyparser'); 

var app = koa() 
app.keys = ['session secret'] 
app.use(session()) 
app.use(bodyParser()) 
csrf(app) 
app.use(csrf.middleware) 

var router = new Router(); 

router.get('/messages', function*() { 
    this.render('new_message_form.html', { 
    token: this.csrf // this call also sets `this.session.secret` for you 
    }); 
}); 

router.post('/messages', function*() { 
    this.assertCSRF(this.request.body); 

    // If we get this far, then the CSRF check passed 
    yield database.insertMessage(this.body.message); 
}); 

app.use(router.routes()); 
app.listen(3000,() => console.log('server listening on 3000')); 

这里就是 'new_message_form.html' 会是什么样子。请注意,我设置了一个隐藏字段_csrf,以便用户提交时,由this.csrf生成的令牌将发送到我的受保护端点,而_csrf字段是koa-csrf检查以查找提交的令牌的位置之一。

<form action="/messages" method="POST"> 
    <input type="hidden" name="_csrf" value="{{ token }}"> 
    <input type="message" name="message" placeholder="Write your message here..."> 
    <button type="submit">Save Message<button> 
</form> 
+0

感谢您的回答。我明白你在那里解释什么。但是,(对不起,如果我不那么清楚),实际上我使用ajax后在服务器上的API休息,并暴露了元数据标记,这是采取与JavaScript的csrf标记。我测试过403消息不是关于令牌丢失,而是关于密钥没有正确设置,消息是不同的。你可以用'koa-generic-session'而不是'koa-session'来重现我的问题,这是不同的。我怀疑'koa-generic-session'和'koa-csrf'之间存在错误的通信。顺便说一句,谢谢,我现在明白了这个键盘阵列的用途。 –

相关问题