如何使用 Node、WS 和 Passport 与 JWT 进行身份验证 Web 套接字?

Zno*_*org 3 websocket node.js express jwt passport.js

我有一个用node/express编写的 Web 服务器,它使用护照通过 JSON Web 令牌(JWT)对用户进行身份验证。

对于常规 HTTP 方法,我使用的是:

app.get('/api/stuff', isLoggedIn(), (req, res) => {
    //get stuff
    res.send( whatever );
});
Run Code Online (Sandbox Code Playgroud)

isLoggedIn这个函数在哪里:

function isLoggedIn() {
    return passport.authenticate('local-jwt', { session: false });
}
Run Code Online (Sandbox Code Playgroud)

身份验证本身是通过'local-jwt'使用JWTStrategy对象的护照中的配置来处理的,并且它按预期工作。

现在我需要向这个应用程序添加网络套接字。我正在使用ws库。这是我到目前为止所拥有的:

const wss = new WebSocket.Server({
    port: 8080,
    verifyClient: async (info, done) => {
        // ???
        done( result );
    }
});

wss.on('connection', ws => {
    // web socket events
});
Run Code Online (Sandbox Code Playgroud)

如何使用护照身份验证仅允许具有正确令牌的客户端连接到 Web 套接字服务器?

C.G*_*hev 5

您可以sign使用用户 ID 或任何用于区分用户的令牌

var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
jwt.sign({
        id: user._id,
        exp: parseInt(exp.getTime() / 1000),
    }, secret);
Run Code Online (Sandbox Code Playgroud)

然后将令牌传递给前端并使用它来初始化您的 Websocket 连接并将其附加到 url 然后在服务器中获取并解码它,如下所示

const wss = new WebSocket.Server({
  verifyClient: async (info, done) => {
    console.log(info.req.url);
    console.log('------verify client------');

    const token = info.req.url.split('/')[1];
    var decoded = jwt.verify(token, secret);

    info.req.user = await User.findById(decoded.id).exec();

    /*info.req.user is either null or the user and you can destroy the connection
     if its null */

    done(info.req);
  },
  server
});
Run Code Online (Sandbox Code Playgroud)

这是多种方法之一。有一种会话方法,但我发现您不想使用它们。另外我不知道你是否使用 mongo 但对于任何数据库都是一样的,你只需要更改一些代码。