Javascript Node.js & Express 会话问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5883821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Node.js & Express session problem
提问by ehynds
I'm having a problem with sessions, where sometimes the session variable I justset is undefined on the next page request. I typically have to go through the flow again in order to properly set the variables.
我遇到了会话问题,有时我刚刚设置的会话变量在下一个页面请求中未定义。我通常必须再次通过流程才能正确设置变量。
I can confirm that I'm not trying to set the session variables to undefined; they have a legit value.
我可以确认我没有尝试将会话变量设置为未定义;它们具有合法的价值。
In my app, users move from /twitter/connect/ to /twitter/callback/. The former retreives some oauth data from twitter, the latter logs the user into twitter.
在我的应用程序中,用户从 /twitter/connect/ 移动到 /twitter/callback/。前者从 twitter 检索一些 oauth 数据,后者将用户登录到 twitter。
/twitter/connect/ is simple:
/twitter/connect/ 很简单:
app.get('/twitter/connect/?', function(req, res){
consumer().getOAuthRequestToken(function(error, oauthToken, oauthTokenSecret, results){
if (error){
// error handling here
} else {
req.session.oauthRequestToken = oauthToken;
req.session.oauthRequestTokenSecret = oauthTokenSecret;
// if I console.log the two session variables above
// they have the proper values.
res.redirect("https://twitter.com/oauth/authorize?oauth_token="+req.session.oauthRequestToken);
}
});
});
After that, twitter sends them back to /twitter/callback/:
之后,twitter 将它们发送回 /twitter/callback/:
app.get('/twitter/callback/?', function(req, res){
console.log(req.session.oauthRequestToken);
console.log(req.session.oauthRequestTokenSecret);
// more often than not, the two variables above are
// undefined. but not always. usually on the first
// pass, never on the second.
});
I have no idea what's going on, I can confirm that the session variables are being set properly, they just aren't holding their value in between page requests, but only the first time.
我不知道发生了什么,我可以确认会话变量设置正确,它们只是在页面请求之间没有保持它们的值,而只是第一次。
This is how I'm creating my server:
这就是我创建服务器的方式:
app.configure('development', function(){
app.use(express.cookieParser());
app.use(express.session({ secret:'yodawgyo' }));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.use(express.logger());
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
app.set('view options', {
open: '{{',
close: '}}'
});
});
I just have a dev environment for now. I have Node 0.5.0-pre installed, but saw this issue on 0.4.1 as well. I'm using express 2.3.2.
我现在只有一个开发环境。我安装了 Node 0.5.0-pre,但在 0.4.1 上也看到了这个问题。我正在使用快递 2.3.2。
Any help is much appreciated.
任何帮助深表感谢。
采纳答案by user2522152
回答by yonran
In Connect's session, any handler can set req.session.anything
to any value, and Connect will store the value when your handler calls end()
. This is dangerous if there are multiple requests in flight at the same time; when they finish, one session value will clobber the other. This is the consequence of having such a simple session API(or see the session sourcedirectly), which has no support to atomically get-and-set session properties.
在 Connect 的会话中,任何处理程序都可以设置req.session.anything
为任何值,当您的处理程序调用 时,Connect 将存储该值end()
。如果同时有多个请求,这很危险;当他们完成时,一个会话值将破坏另一个。这是拥有如此简单的会话 API(或直接查看会话源)的结果,它不支持原子地获取和设置会话属性。
The workaround is to try to give the session middleware as few of the requests as necessary. Here are some tips:
解决方法是尝试尽可能少地为会话中间件提供必要的请求。以下是一些提示:
- Put your
express.static
handler above the session middleware. - If you can't move up some handlers that don't need the session, you can also configure the session middleware to ignore any paths that don't use
req.session
by sayingexpress.session.ignore.push('/individual/path')
. - If any handler doesn't write to the session (maybe it only reads from the session), set
req.session = null;
before callingres.end();
. Then it won't be re-saved.
- 将您的
express.static
处理程序放在会话中间件之上。 - 如果您不能上移一些不需要会话的处理程序,您还可以配置会话中间件以忽略任何不使用
req.session
的路径,只需说express.session.ignore.push('/individual/path')
. - 如果任何处理程序没有写入会话(也许它只从会话中读取),请
req.session = null;
在调用res.end();
. 那么它就不会被重新保存。
If only one request does a read-modify-write to the session at a time, clobbering will be less likely. I hope that in the future, Connect will have a more precise session middleware, but of course the API will be more complicated than what we have now.
如果一次只有一个请求对会话执行读-修改-写操作,那么破坏的可能性就会降低。我希望在未来,Connect 会有更精确的会话中间件,但当然 API 会比我们现在拥有的更复杂。
回答by Yevgeniy Brikman
I filed an issue against Express about github, but figured out what was wrong a few minutes later. Not sure if you're having the same problem, but for completeness:
我向Express提交了一个关于 github的问题,但几分钟后发现出了什么问题。不确定您是否遇到同样的问题,但为了完整性:
In my case, I was testing by going to http://localhost:8003but the OAuth provider was redirecting to http://hostname:8003. Same box/server/webpage, but different domain names means the browser sends different cookies and consequently, express gets different session ids and session data. As soon as I started testing at http://hostname:8003, everything worked just fine.
就我而言,我通过转到http://localhost:8003进行测试,但 OAuth 提供程序正在重定向到http:// hostname:8003。相同的盒子/服务器/网页,但不同的域名意味着浏览器发送不同的 cookie,因此 express 获得不同的会话 ID 和会话数据。我一开始在http:// hostname:8003 上测试,一切都很好。
回答by Anwar Hahj Jefferson-George
My code was similar to yours, structurally. In my case, however, my POST operation originated from the JQuery $.post function. I don't know if that makes an appreciable difference, however
我的代码在结构上与你的相似。然而,就我而言,我的 POST 操作源自 JQuery $.post 函数。我不知道这是否有明显的不同,但是
What I ended up having to do was send a "junk" response at the end of the POST operation definition in my express routing routine, i.e.
我最终要做的是在我的快速路由例程中的 POST 操作定义的末尾发送一个“垃圾”响应,即
res.send("hoo hee ha ha unimportant junk data");
res.send("hoo hee ha ha unimportant junk data");
By including this at the end I was able to trigger a success function (the callback for the AJAX post attempt). I inserted the redirect there, instead of placing it in the express routes.
通过在最后包含它,我能够触发成功函数(AJAX 发布尝试的回调)。我在那里插入了重定向,而不是将它放在快速路由中。
Use with AJAX Post window.redirect();
与 AJAX 帖子一起使用 window.redirect();
Do not use with AJAX Post: $res.redirect("someurl");
不要与 AJAX Post 一起使用: $res.redirect("someurl");
This is because browsers apparently will not redirect on AJAX response, so you have to use Javascript, as described here: Express js - can't redirect
这是因为浏览器显然不会在 AJAX 响应上重定向,因此您必须使用 Javascript,如下所述:Express js - 无法重定向
Hope that helps someone, it fixed the problem for me, peace.
希望能帮助某人,它为我解决了问题,和平。