Nodejs Socket.io 验证

Nodejs Socket.io 验证

客户端:index.html

<html>
<head>
    <script src="http://localhost:3000/socket.io/socket.io.js" type="text/javascript"></script>
    <script type="text/javascript">
        tick = io.connect('http://localhost:3000/');
        tick.on('data', function (data) {
            console.log(data);
        });

        tick.on('error', function (reason){
          console.error('Unable to connect Socket.IO', reason);
        });

        tick.on('connect', function (){
          console.info('successfully established a working and authorized connection');
        });
    </script>
</head>
<body>
    Open the browser console to see tick-tocks!
</body>
</html>

设置Express

var app = express();

app.configure(function () {
    app.use(express.cookieParser());
    app.use(express.session({secret: 'secret', key: 'express.sid'}));
});


app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});

server = http.createServer(app)
server.listen(3000);

设置Socket.IO

io = io.listen(server);

io.set('authorization', function (handshakeData, accept) {

if (handshakeData.headers.cookie) {

handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);

handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['express.sid'],     'secret');

if (handshakeData.cookie['express.sid'] == handshakeData.sessionID) {
  return accept('Cookie is invalid.', false);
}

} else {
    return accept('No cookie transmitted.', false);
} 

accept(null, true);
});

3 回复

为了实现 Node.jsSocket.IO 的验证机制,我们需要确保客户端与服务器之间的连接是经过身份验证的。这里我们将通过检查 cookie 来验证客户端的身份。

客户端代码 (index.html)

首先,客户端需要加载 Socket.IO 库,并尝试连接到服务器:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Socket.IO Authentication Example</title>
    <script src="http://localhost:3000/socket.io/socket.io.js" type="text/javascript"></script>
    <script type="text/javascript">
        var socket = io.connect('http://localhost:3000/', {
            transports: ['websocket'],
            query: "authToken=yourAuthToken"
        });

        socket.on('connect', function () {
            console.info('Successfully established a working and authorized connection');
        });

        socket.on('data', function (data) {
            console.log(data);
        });

        socket.on('error', function (reason) {
            console.error('Unable to connect Socket.IO', reason);
        });
    </script>
</head>
<body>
    Open the browser console to see tick-tocks!
</body>
</html>

服务器端代码

接下来,在服务器端设置 ExpressSocket.IO,并添加身份验证逻辑:

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const connect = require('connect'); // Ensure you have this package installed

const app = express();

// 设置中间件
app.use(cookieParser());
app.use(session({
    secret: 'secret',
    key: 'express.sid'
}));

app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});

const server = http.createServer(app);
const io = socketIo.listen(server);

io.set('authorization', function (handshakeData, accept) {
    if (handshakeData.headers.cookie) {
        const cookies = cookieParser.parse(handshakeData.headers.cookie);
        const sessionID = cookies['express.sid'];

        // 检查 session ID 是否有效
        if (!sessionID || !connect.utils.parseSignedCookie(sessionID, 'secret')) {
            return accept('Session ID is invalid.', false);
        }
    } else {
        return accept('No cookie transmitted.', false);
    }

    accept(null, true);
});

io.on('connection', function (socket) {
    console.log('A user connected');
    
    socket.on('disconnect', function () {
        console.log('User disconnected');
    });
});

server.listen(3000, () => {
    console.log('Server running on port 3000');
});

解释

  1. 客户端:客户端发送一个带有 authToken 的查询参数,这在实际应用中可以替换为任何有效的认证信息。

  2. 服务器端:使用 express-session 中间件来管理会话。当客户端尝试连接时,服务器通过检查 cookie 中的 express.sid 来验证用户的身份。如果 cookie 无效或不存在,连接将被拒绝。

通过这种方式,我们可以确保只有经过身份验证的客户端才能与服务器建立有效的 WebSocket 连接。


能讲下 做什么用的吗

为了确保在使用Socket.io时进行有效的验证,我们可以利用Session信息来验证客户端的身份。以下是一个简化的示例代码,展示如何在Node.js中配置Socket.io以实现客户端的身份验证。

首先,我们需要确保客户端请求包含正确的Cookie。在服务端,我们将使用cookie-parserexpress-session中间件来解析和管理Session信息。接着,在Socket.io的授权过程中,我们将检查客户端是否提供了有效的Session信息。

客户端代码 (index.html)

客户端代码不需要修改,因为它已经通过socket.io.js库连接到服务器,并且监听了相关的事件。

<html>
<head>
    <script src="http://localhost:3000/socket.io/socket.io.js" type="text/javascript"></script>
    <script type="text/javascript">
        var socket = io.connect('http://localhost:3000/');

        socket.on('data', function (data) {
            console.log(data);
        });

        socket.on('error', function (reason) {
            console.error('Unable to connect Socket.IO', reason);
        });

        socket.on('connect', function () {
            console.info('Successfully established a working and authorized connection');
        });
    </script>
</head>
<body>
    Open the browser console to see tick-tocks!
</body>
</html>

服务端代码

服务端需要引入必要的依赖项,并配置cookie-parserexpress-session以及Socket.io

const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const connect = require('connect'); // 注意这里可能需要安装额外的包如`connect`或使用其他方法来处理session
const cookie = require('cookie');

const app = express();
app.use(cookieParser());
app.use(session({
    secret: 'secret',
    key: 'express.sid'
}));

app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

const server = http.createServer(app);
const io = socketIo.listen(server);

io.set('authorization', function (handshakeData, accept) {
    if (handshakeData.headers.cookie) {
        handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
        handshakeData.sessionID = connect.utils.parseSignedCookie(handshakeData.cookie['express.sid'], 'secret');
        
        if (!handshakeData.sessionID || handshakeData.sessionID !== handshakeData.cookie['express.sid']) {
            return accept('Invalid session cookie', false);
        }
    } else {
        return accept('No cookie transmitted.', false);
    }

    accept(null, true);
});

server.listen(3000, () => {
    console.log('Server listening on port 3000');
});

解释

  1. 客户端:客户端尝试通过Socket.io与服务器建立连接。如果连接成功,它会在控制台输出一条消息。
  2. 服务端
    • 使用cookie-parserexpress-session中间件来解析和管理会话。
    • 在Socket.io的authorization函数中,我们检查传入的HTTP请求头中是否包含有效的Cookie。如果Cookie有效,则接受连接;否则,拒绝连接。

这样,我们就实现了基本的身份验证机制,确保只有经过身份验证的用户才能建立Socket.io连接。

回到顶部