草庐IT

node.js - socket.io 和 express 4 个 session

coder 2023-05-30 原文

我想在我的 socket.io 应用程序中访问 express 4 session 。 我是 Node 的新手,在实现这个功能时遇到了一些麻烦。

我发现了一个允许访问 express 4 session 的 npm 模块:https://www.npmjs.org/package/session.socket.io-express4https://github.com/eiriklv/session.socket.io

如果您查看下面我的 app.js 代码,我在 sessionsessionStorecookieParser 设置中做错了,因为我就是无法让这个模块工作。

// init modules
var express = require('express');
var helmet = require('helmet');
var fs = require('fs');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var memoryStore = session.MemoryStore;
var app = express();

// set variables
var options = {
  key: fs.readFileSync('./openssl_keys/server_key.pem'),
  cert: fs.readFileSync('./openssl_keys/server_cert.pem')
};
var cookieSecret = "secret phrase";
var sessionStore = new memoryStore();

app.set('env', process.env.NODE_ENV || 'development');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser(cookieSecret));
app.use(session({
    secret: cookieSecret,
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
app.use(function(req, res, next){
    res.locals.session = req.session;
    next();

});
app.use(express.static(path.join(__dirname, 'public')));

//routes
require('./routes/index')(app);
require('./routes/test')(app);


// starting http and https servers
var http = require('http').createServer(app).listen(8000, function(){
    console.log("http server listening on port 8000");
});
var https = require('https').createServer(options, app).listen(8080, function(){
    console.log("https server listening on port 8080"); 
});

// starting socket.io & session handler
var serverIO = require('socket.io').listen(https);
var SessionSockets  = require('session.socket.io-express4');
var io = new SessionSockets(serverIO, sessionStore, cookieParser);

io.on('connection', function(err, socket, session){
    if(err) throw err;
    console.log("connected");
    //console.log(session);
    socket.on('clientMessage', function(content) {
        console.log("received client message")
        console.log(content);
    });

});

module.exports = app;

我尝试了多种可能性,例如:

  • 禁用 https 服务器。
  • 使用密码短语设置 cookieParser 对象(因此它“实际上”将密码短语导出到 io = new SessionSockets(serverIO, sessionStore, cookieParser);)
  • 使用最少的 cookie 选项。

无论如何我对此有点迷茫,欢迎任何建议/批评。


更新

好的,经过多次尝试,我想我可以让它工作!

问题在于 cookieParser 初始化,正确的方法似乎是:

var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());

请注意,如果我使用 var io = new SessionSockets(serverIO, sessionStore, cookieParser);(而不是 cookieParser())那么它就不起作用。 这似乎是问题所在。

如果我使用:

app.use(cookieParser("secret phrase"));
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser("secret phrase"));

然后模块崩溃并显示以下错误消息:

session.socket.io-express4/session.socket.io.js:41
ake.signedCookies[key] = handshake.signedCookies[key].match(/\:(.*)\./).pop();
                                                                        ^
TypeError: Cannot call method 'pop' of null

但如果我使用:

app.use(cookieParser("secret phrase"));
app.use(session({
    secret: "secret phrase",
    cookie: {httpOnly: true, secure: true},
    store: sessionStore
}));
var io = new SessionSockets(serverIO, sessionStore, cookieParser());

然后一切看起来都很好。

现在,在 cookie-parser 文档 (https://github.com/expressjs/cookie-parser) 中,您可以传递一个 key 来获得 cookie 的签名。这是我想要的。

有人可以解释一下 cookie-parser 密码短语和 session 密码短语的关系吗?它们必须相同/不同吗?

最佳答案

这是我针对以下环境的解决方案:

  • 表达 4.2.0
  • socket.io 1.1.0
  • cookie 解析器 1.0.1
  • cookie session 1.0.2

代码:

var cookieParser = require('cookie-parser')();
var session = require('cookie-session')({ secret: 'secret' };

...

app.use(cookieParser);
app.use(session);

...

io.use(function(socket, next) {
    var req = socket.handshake;
    var res = {};
    cookieParser(req, res, function(err) {
        if (err) return next(err);
        session(req, res, next);
    });
});

然后你可以通过套接字的握手访问 session :

io.on('connection', function (socket) {
    console.log("Session: ", socket.handshake.session);
});

对于想知道它如何/为什么起作用的人:

  • 我们通过 cookie 解析器发送 handshake 请求,以便 cookie 可用
  • 然后我们通过 session 中间件发送 handshake,就好像它是一个正常的请求一样
  • 中间件将 session 附加到请求中
  • 我们使用 handshake 是因为出于所有意图和目的,这是一个正常的请求,解析器和 session 中间件可以正确处理它。这就是为什么您必须通过 handshake
  • 访问 session

关于node.js - socket.io 和 express 4 个 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23494016/

有关node.js - socket.io 和 express 4 个 session的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  5. ruby-on-rails - Rails 优雅地处理超时 session ? - 2

    使用rails4,ruby2。我在rails配置中为我的cookiesession设置了30分钟的超时时间。问题是,如果我转到表单,让session超时,然后提交表单,我会收到此ActionController::InvalidAuthenticityToken错误。如何在Rails中优雅地处理这个错误?比如说,重定向到登录屏幕? 最佳答案 在您的ApplicationController:rescue_fromActionController::InvalidAuthenticityTokendoredirect_tosome_p

  6. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  7. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  8. ruby - Sinatra session 未按预期持续 - 2

    我正在尝试使用Sinatra中的重定向和session在网站周围传递一些数据。这是一个简化的示例,使用PrettyPrint进行调试:require'pp'require'rubygems'require'sinatra'enable:sessionsget'/'dosession[:foo]='12345'puts'session1'ppsessionredirectto('/redir')endget'/redir'doputs'session2'ppsession'helloworld'end查看Thin的输出,我看到:>>Listeningon0.0.0.0:4567,CTRL

  9. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

  10. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

随机推荐