使用socket.io,如何处理非浏览器客户端的身份验证?

3
我正在尝试使用 socket.io 对 WebSocket 连接进行身份验证。
我的 WebSockets 可以从浏览器、Python 或 Node.js 客户端接收连接。
在第一种情况下(浏览器),用户通过我的 Express.js 服务器进行身份验证,因此我只需使用会话 cookie,所以没有问题。
然而,在第二种情况下(随机客户端),我需要自己处理身份验证。
我从 socket.io 文档中发现,有一个钩子可以在握手阶段授权连接。但是,似乎客户端无法添加自定义标头。看起来唯一的添加自定义数据的方法是在 URL 查询字符串中
对我来说,这似乎并不真正安全,因为 URL 是常见的日志记录对象,因此凭据也将被记录。

另外,我想知道在握手期间连接是否安全,如果握手不是通过ssl完成的,那么这样做就存在重大安全问题。

基本上涉及安全方面的担忧。有人知道正确的做法吗?我真的需要将凭据放在url中吗?那样安全吗?


2
你已经正确地猜到了在URL中放置凭据是一个非常糟糕的想法。如果您设置了SSL,您的URL在传输过程中会被加密,因此窃听者无法看到它;然而,主要风险是URL可能会在服务器上记录在各个位置,因此任何可以查看日志的人(管理员或入侵您服务器的人)都可以学习到一堆明文密码。 - apsillers
是啊...我知道。但是到目前为止我还没有看到其他的解决方案!? - sebpiq
3个回答

0

对于这样的尝试,您需要将expressID钩入socketIO连接的sessionID中。对于express 3来说,这是一个完全不同的故事,通常并不容易。几个月前,我找到了一种方法来实现这一点。

//directories
var application_root = __dirname,

//general require
var express = require('express'),
 connect = require('connect'),
 http = require('http');

//create express app
var app = express();

//create sessionStore
var sessionStore = new connect.session.MemoryStore();

//setup sessionKey
var secretKey = 'superdupersecret';


//configure express
app.configure(function() {

    //use body parser
    app.use(express.bodyParser());

    //override methods
    app.use(express.methodOverride());

    //cookies and sessions
    app.use(express.cookieParser(secretKey));
    app.use(express.session({
        store: sessionStore,
        secret: secretKey,
        key: 'express.sid'
    }));

    //router
    app.use(app.router);
});

//create the http server link to the new data http object of express 3
server = http.createServer(app);

//make server listen to 8080 and localhost requests
server.listen(8080, 'localhost', function() {
    console.log('Express Server running and listening');
});

//bind socket.io to express server by listening to the http server object
var io = require('socket.io').listen(server);

//set the authorization through cookies 
io.set('authorization', function(data, accept) {

//check if header data is given from the user
if (!data.headers.cookie) {

        //return false if no cookie was given
        return accept('Session cookie required!', false);
    }

    //parse cookie into object using the connect method
    //NOTE: this line is a hack, this is due to the fact
    //that the connect.utils.parseCookie has been removed
    //from the current connect module and moved to an own
    //instance called 'cookie'.
    data.cookie = connect.utils.parseSignedCookies(require('cookie').parse(decodeURIComponent(data.headers.cookie)), secretKey);

    //save session id based on exress.sid
    data.sessionID = data.cookie['express.sid'];

    //get associated session for this id
    sessionStore.get(data.sessionID, function(err, session) {
        if (err) {
            //there was an error
            return accept('Error in session store.', false)
        } else if (!session) {
            //session has not been found
            return accept('Session not found', false);
        }

        //successfully got the session, authed with known session
        data.session = session;

        //return the accepted connection
        return accept(null, true);
    });

});

//connection handler for new io socket connections
io.sockets.on('connection', function(socket) {

    //parse handshake from socket to io
    var hs = socket.handshake;

    //show session information
    console.log('New socket connection with sessionID ' + hs.sessionID + ' connected');

});

//handle user disconnect and clear interval
io.sockets.on('disconnect', function() {

    //show disconnect from session
    console.log('Socket connection with sessionID ' + hs.sessionID + ' disconnected');

});

是的...但正如我所说,这仅在存在cookie时有效,即当连接由浏览器发起并从Express获取cookie时。 - sebpiq
好的,否则我看不到任何可行的身份验证方法。由于代理黑客等问题,您无法使用IP。 - toxicate20
socket.io-client跟踪器中有一个未解决的问题,我在这篇文章中提供了链接。 - sebpiq

0
这对我有用:https://gist.github.com/jfromaniello/4087861。我必须更改socket.io-client package.json以使用xmlhttprequest版本1.5.0,该版本允许设置cookie头。我还必须更改两个requires以使用socket.io xmlhttprequest:
require('socket.io-client/node_modules/xmlhttprequest') 

替代

require ('xmlhttprequest');

0

所以看起来唯一的解决方案就是在URL查询字符串中添加您的身份验证数据。有一个开放票务来允许其他可能性,但看起来开发人员更倾向于仅使用查询字符串。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接