返回

Nest如何简单便捷地实现带身份验证的GraphQL订阅功能

前端

前言

最近在用Nest+GraphQL做一个消息推送的功能,但发现相关资料真的好少,不仅官网文档没有详细介绍,社区中也少有人讨论。所以写了这个文章,希望可以帮助到有需要的人。

概述

GraphQL订阅允许客户端订阅服务器上的事件。当事件发生时,服务器会将事件数据推送到客户端。这使得客户端可以实时更新数据,而无需不断轮询服务器。

实现

1. 安装依赖

npm install @nestjs/graphql @nestjs/websockets graphql-ws socket.io

2. 创建GraphQL订阅解析器

import { Injectable } from '@nestjs/common';
import { PubSub } from 'graphql-subscriptions';
import { Message } from './message.entity';

@Injectable()
export class MessageService {
  private pubSub = new PubSub();

  addMessage(message: Message): Message {
    this.pubSub.publish('messageAdded', { messageAdded: message });
    return message;
  }

  async getMessages(): Promise<Message[]> {
    return [];
  }
}

3. 创建WebSocket网关

import { Injectable } from '@nestjs/common';
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { MessageService } from './message.service';
import { Message } from './message.entity';

@WebSocketGateway()
export class MessageGateway {
  constructor(private messageService: MessageService) {}

  @SubscribeMessage('messageAdded')
  handleMessageAdded(@MessageBody() data: Message): void {
    this.messageService.addMessage(data);
  }
}

4. 配置GraphQL模块

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { MessageModule } from './message.module';

@Module({
  imports: [
    GraphQLModule.forRoot({
      typePaths: ['./**/*.graphql'],
      installSubscriptionHandlers: true,
    }),
    MessageModule,
  ],
})
export class AppModule {}

5. 使用JWT进行身份验证

为了对GraphQL订阅进行身份验证,我们需要使用JWT。首先,我们需要安装@nestjs/jwt包:

npm install @nestjs/jwt

然后,我们需要创建一个JWT服务:

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
  constructor(private jwtService: JwtService) {}

  login(user: any): string {
    const payload = { username: user.username, sub: user.id };
    return this.jwtService.sign(payload);
  }
}

接下来,我们需要在GraphQL模块中配置JWT服务:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { MessageModule } from './message.module';
import { AuthService } from './auth.service';

@Module({
  imports: [
    GraphQLModule.forRoot({
      typePaths: ['./**/*.graphql'],
      installSubscriptionHandlers: true,
      context: ({ req }) => ({ req }),
    }),
    MessageModule,
  ],
  providers: [AuthService],
})
export class AppModule {}

最后,我们需要在WebSocket网关中添加身份验证:

import { Injectable } from '@nestjs/common';
import { WebSocketGateway, SubscribeMessage, MessageBody } from '@nestjs/websockets';
import { MessageService } from './message.service';
import { Message } from './message.entity';
import { JwtService } from '@nestjs/jwt';

@WebSocketGateway()
export class MessageGateway {
  constructor(private messageService: MessageService, private jwtService: JwtService) {}

  @SubscribeMessage('messageAdded')
  handleMessageAdded(@MessageBody() data: Message, @Request() req: any): void {
    const token = req.headers.authorization.split(' ')[1];
    const payload = this.jwtService.decode(token);
    if (payload && payload.username === 'admin') {
      this.messageService.addMessage(data);
    }
  }
}

总结

以上就是如何在Nest中实现带身份验证的GraphQL订阅的方法。希望对大家有所帮助。