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

NestJS WebSocket网关异常过滤器无法触发问题求助

WebSocket异常过滤器未触发的问题解决

问题原因

NestJS的WebSocket异常过滤器默认仅作用于被@SubscribeMessage()装饰的消息处理方法,而handleConnection、handleDisconnect这类生命周期钩子中抛出的异常,不会自动被过滤器捕获。你的代码中异常是在handleConnection调用的auth方法中抛出的,因此过滤器的catch方法不会被触发。

解决方案

方案1:手动捕获并处理异常

直接在handleConnection中用try/catch包裹认证逻辑,手动处理错误:

handleConnection(client: WebSocket, req: any) {
    console.log('connecting');
    try {
        this.auth(req);
    } catch (error) {
        // 发送错误消息给客户端
        client.send(JSON.stringify({
            error: error instanceof WsException ? error.getError() : 'Authentication failed'
        }));
        // 关闭连接
        client.close(401, 'Unauthorized');
    }
}

方案2:手动调用过滤器

如果你希望复用已有的WebSocketExceptions过滤器,可以在catch块中手动调用过滤器的catch方法,需要手动构造ArgumentsHost:

import { ArgumentsHost } from '@nestjs/common';

// ...

handleConnection(client: WebSocket, req: any) {
    console.log('connecting');
    const filter = new WebSocketExceptions();
    try {
        this.auth(req);
    } catch (error) {
        // 构造WebSocket类型的ArgumentsHost
        const host = ArgumentsHost.create([
            'ws', // 上下文类型
            client, // WebSocket客户端实例
            req, // 请求对象
        ]);
        filter.catch(error, host);
    }
}

方案3:改用WebSocket守卫处理认证(推荐)

将认证逻辑移到WebSocket守卫中,守卫会在handleConnection执行前拦截请求,认证失败时直接关闭连接:

  1. 创建守卫:
// ws-auth.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { WsException } from '@nestjs/websockets';
import { verify } from 'jsonwebtoken';
import { config } from 'src/config';
import { IncomingMessage } from 'http';

@Injectable()
export class WsAuthGuard implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        const client = context.switchToWs().getClient();
        const req: IncomingMessage = context.switchToWs().getData(); // 连接阶段的请求对象通过getData获取

        const token = this.extractTokenFromHeader(req);
        if (!token) {
            client.close(401, 'No Token');
            throw new WsException('No Token');
        }

        try {
            verify(token, config.serviceSecret);
            return true;
        } catch (error) {
            client.close(401, 'Invalid Token');
            throw new WsException('Invalid Token');
        }
    }

    private extractTokenFromHeader(req: IncomingMessage): string | undefined {
        const [type, token] = req.headers.authorization?.split(' ') ?? [];
        return type === 'Bearer' ? token : undefined;
    }
}
  1. 在网关中使用守卫:
@WebSocketGateway({ path: '/ws/operator' })
@UseGuards(WsAuthGuard) // 添加守卫
export class WsOperatorServiceGateway implements OnGatewayConnection, OnGatewayDisconnect {
    handleConnection(client: WebSocket, req: any) {
        console.log('connecting');
        // 认证已通过,无需再调用auth方法
    }

    // ...其他方法
}

内容的提问来源于stack exchange,提问作者user24484638

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 20:56:02