注销并获取新/ csrfToken后,SailsJS CSRF不匹配

我正在创build单页面应用程序。 我创build了login注销操作,他们工作正常。 但是,如果用户注销并且不会刷新浏览器中的页面,则由于“CSRF不匹配”错误而无法再次login。

脚步:

1.在第一次加载页面时,csrf是view local:

<div class="app" id="app" data-csrf="<%= _csrf %>"></div> 

2.用户使用此令牌成功login:

 420["post",{"method":"post","headers":{},"data":{"_csrf":"VHcT2F44-KhZMJmhcAVB1H69BgTMWMZji9_8","login":"alex","password":"123"},"url":"http://127.0.0.1:1337/login"}] 430[{"body":{"id":"560e5756cd01633407eea8be"},"headers":{cut headers},"statusCode":200}] 

3.然后,用户使用此令牌注销:

 421["post",{"method":"post","headers":{},"data":{"_csrf":"VHcT2F44-KhZMJmhcAVB1H69BgTMWMZji9_8"},"url":"http://127.0.0.1:1337/logout"}] 431[{"body":"ok","headers":{cut headers},"statusCode":200}] 

4.如果他再次尝试login,他会发现“CSRF不匹配”错误,我期望:

 422["post",{"method":"post","headers":{},"data":{"_csrf":"VHcT2F44-KhZMJmhcAVB1H69BgTMWMZji9_8","login":"alex","password":"123"},"url":"http://127.0.0.1:1337/login"}] 432[{"body":"CSRF mismatch","headers":{},"statusCode":403}] 

5.我正在捕获这个错误,并按照文档中的说法执行/ csrfToken请求

 423["get",{"method":"get","headers":{},"data":{},"url":"/csrfToken"}] 433[{"body":{"_csrf":"49C5OVUZ-6SIL_zW3g1NGI87ux6Mlp-UJj_w"},"headers":{cut headers},"statusCode":200}] 

6.尝试使用新令牌重新login:

 424["post",{"method":"post","headers":{},"data":{"_csrf":"49C5OVUZ-6SIL_zW3g1NGI87ux6Mlp-UJj_w","login":"alex","password":"123"},"url":"http://127.0.0.1:1337/login"}] 434[{"body":"CSRF mismatch","headers":{},"statusCode":403}] 

我可以用相同的结果重复步骤5和6。

如果我刷新页面,我可以无误地login。 问题是,发生了什么事? 为什么步骤6中的标记不匹配?

编辑:注销方法:

 req.session.destroy(); return res.send("ok"); 

编辑2:发送请求:

 import socketIOClient from 'socket.io-client'; import sailsIOClient from 'sails.io.js'; var io = sailsIOClient(socketIOClient); io.socket.post(form.action, serialize(form, {hash: true}), function (data, jwres){ ... }); 

TL; DR:使用req.session.csrfSecret = null而不是req.session.destroy()如果你正在做所有的套接字。


这里的问题是Express会话的工作方式。 当您调用.destroy()时,它会删除Express MemoryStore维护的sessions对象中当前会话标识(SID)的条目。 通常情况下,这很好,因为它会在下一个请求中重新生成,但这只是运行所有Express中间件的下一个请求 – 并且对Sails应用的Socket请求不会这样做,因为任何尝试使用Sails的Passport这个盒子会告诉你的。 所以下一次你发出一个套接字请求(产生一个新的CSRF秘密并获得一个新的令牌),你实际上并没有连接到一个会话,新的信息不会被保存。

如果不是销毁整个会话,而只是销毁用于生成CSRF令牌的csrfSecret ,则下一个套接字请求仍将附加到会话中,新的密钥将被保存。 您还需要清除保留用户login的任何其他会话variables。