You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AdonisJS v4.1 Socket.IO JWT认证:auth变量未定义求助

解决AdonisJS v4.1中Socket.IO JWT认证时auth变量未定义的问题

Hey Corné, let's break down why your auth variable is coming up undefined and get your Socket.IO authentication working properly.

问题根源

First off, the auth parameter you're trying to destructure in playerLogin isn't being passed when you call the method (you're only sending socket and io as arguments). Even if you did pass it, AdonisJS's auth service is tied to HTTP request contexts by default—Socket.IO connections don't have that built-in context, so you can't inject it directly like you would in a regular HTTP controller method.

解决方案步骤

1. 手动引入并使用Auth服务

Since you're using static controller methods (which don't support Adonis's dependency injection), we'll grab the Auth service directly from the IoC container. Here's how to update your AuthenticateController.js:

const Hash = use('Hash')
const User = use('App/Models/User')
const Auth = use('Auth') // 手动从IoC容器获取Auth服务

class AuthenticateController {
  static async playerLogin(socket, io) {
    socket.on('playerLogin', async (data) => {
      try {
        // 先查找用户
        const user = await User.findBy('email', data.email)
        if (!user) {
          return socket.emit('sendPlayerToken', { token: 'Credentials are incorrect' });
        }
        
        // 验证密码是否匹配
        const isPasswordValid = await Hash.verify(data.password, user.password)
        if (!isPasswordValid) {
          return socket.emit('sendPlayerToken', { token: 'Credentials are incorrect' });
        }

        // 生成JWT token
        const accessToken = await Auth.generate(user)
        socket.emit('sendPlayerToken', { token: accessToken });
      } catch (error) {
        socket.emit('sendPlayerToken', { token: 'Authentication failed', error: error.message });
      }
    });
  }

  static playerRegister(socket, io) {
    socket.on('playerRegister', async (data) => {
      try {
        const safePassword = await Hash.make(data.password)
        // 用create方法简化用户创建逻辑
        const user = await User.create({
          username: data.username,
          email: data.email,
          password: safePassword
        })
        socket.emit('sendPlayerRegister', { success: true, userId: user.id });
      } catch (error) {
        socket.emit('sendPlayerRegister', { success: false, error: error.message });
      }
    });
  }
}

module.exports = AuthenticateController

2. 可选:验证Socket连接时的JWT Token

If you want to authenticate users when they first connect to Socket.IO (using an existing JWT token), you can add this logic to your start/socket.js to validate the token and attach the user to the socket object:

const Server = use('Server')
const io = use('socket.io')(Server.getInstance())
const AuthenticateController = use('App/Controllers/Http/AuthenticateController');
const Auth = use('Auth')

io.on('connection', async function (socket) {
  // 从握手信息中获取token(可能在query参数或headers里)
  const token = socket.handshake.query.token || socket.handshake.headers['authorization']?.split(' ')[1];
  
  if (token) {
    try {
      // 验证token并获取用户信息
      const user = await Auth.verify(token)
      socket.user = user // 将用户挂载到socket上,后续事件可直接使用
      console.log(`User ${user.email} connected via Socket.IO`)
    } catch (error) {
      console.log('Invalid Socket.IO token:', error.message)
      socket.disconnect(true) // 验证失败则断开连接
      return
    }
  }

  // 绑定控制器方法
  AuthenticateController.playerLogin(socket, io);
  AuthenticateController.playerRegister(socket, io);
})

3. 确认Auth配置正确

Double-check your config/auth.js to ensure the JWT driver is set up correctly (using your app's secret key):

module.exports = {
  authenticator: 'jwt',

  jwt: {
    driver: 'jwt',
    model: 'App/Models/User',
    scheme: 'jwt',
    uid: 'email',
    password: 'password',
    options: {
      secret: Env.get('APP_KEY'),
      expiresIn: '7d' // 可根据需求调整过期时间
    }
  },
  // ...其他认证配置
}

关键要点

  • AdonisJS's auth service is built for HTTP requests—Socket.IO connections don't have a request context, so we need to manually fetch the Auth service from the IoC container.
  • For login requests, we replicate the HTTP login flow: find the user, verify their password, then generate a token with Auth.generate().
  • If you need authenticated Socket.IO events, validating the token on connection and attaching the user to the socket object lets you access the user in all subsequent events.

内容的提问来源于stack exchange,提问作者Corné Den Breejen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:37:23