如何从控制器头中获取JWT令牌

时间:2019-09-07 12:25:34

标签: controller request http-headers nestjs

请帮助我找到如何优化代码。 我需要限制登录用户的数据。为此,我需要从Request的JWT令牌中获取UUID。但是我不喜欢我的方法,因为我有重复的代码:

const jwt = request.headers.authorization.replace('Bearer ', '');
const json = this.jwtService.decode(jwt, { json: true }) as { uuid: string };

有人知道我该如何优化吗?

这是我控制器的代码。

import { Controller, Get, Put, Body, Param, UseGuards, Req } from '@nestjs/common';
import { SettingService } from '../services';
import { AuthGuard } from '@nestjs/passport';
import { ResultInterface } from '../interfaces';
import { Request } from 'express';
import { JwtService } from '@nestjs/jwt';

@Controller('settings')
export class SettingController {
  /**
   * @param service
   * @param jwtService
   */
  constructor(private readonly service: SettingService,
              private readonly jwtService: JwtService) {
  }

  @UseGuards(AuthGuard('jwt'))
  @Get()
  async findAll(@Req() request: Request): Promise<ResultInterface> {
    const jwt = request.headers.authorization.replace('Bearer ', '');
    const json = this.jwtService.decode(jwt, { json: true }) as { uuid: string };
    const data = await this.service.findAll(json.uuid);
    return { rows: data };
  }

  @UseGuards(AuthGuard('jwt'))
  @Get(':id')
  async findOne(@Param('id') id: number, @Req() request: Request): Promise<ResultInterface> {
    const jwt = request.headers.authorization.replace('Bearer ', '');
    const json = this.jwtService.decode(jwt, { json: true }) as { uuid: string };
    const data = await this.service.findOneById(id, json.uuid);
    return { row: data };
  }

  @UseGuards(AuthGuard('jwt'))
  @Put()
  update(@Body() data: any, @Req() request: Request): Promise<any> {
    const jwt = request.headers.authorization.replace('Bearer ', '');
    const json = this.jwtService.decode(jwt, { json: true }) as { uuid: string };
    return this.service.update(data, json.uuid);
  }
}

2 个答案:

答案 0 :(得分:2)

您可以创建一个JWTUtil来为您执行此操作……也许像这样?

@Injectable()
export class JWTUtil {
    constructor(private readonly jwtService: JWTService) {}

    decode(auth: string): {uuid: string}{
        const jwt = auth.replace('Bearer ', '');
        return this.jwtService.decode(jwt, { json: true }) as { uuid: string };
    }
}

然后像这样使用它:

@Controller('settings')
export class SettingController {
  constructor(
      private readonly jwtUtil: JWTUtil,
      private readonly service: SettingService,
      ) {}

  @Get()
  @UseGuards(AuthGuard('jwt'))
  async findAll(@Headers('Authorization') auth: string): Promise<ResultInterface> {
    const json = await this.jwtUtil.decode(auth);
    const data = await this.service.findAll(json.uuid);

    //....
  }
}

还要注意,您可以直接从控制器访问Authorization标头。而不是通过Request对象。

答案 1 :(得分:2)

为了使您的代码更具可读性和透明度,您可以创建一个@AuthUser()装饰器,并在所有控制器中重用它。使用AuthGuard('jwt')时,您已经在解码令牌;如果再次使用jwt.decode函数,则需要对令牌进行双解码。

我在下面附上了一个用户装饰器和返回我所有订单的订单控制器功能示例。

user.decorator.ts

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

export const AuthUser = createParamDecorator((data, req) => {
  return req.user;
});

order.controller.ts

 @ApiOperation({ title: 'Get my orders' })
 @Get('/me')
 @UseGuards(AuthGuard('jwt'))
 async findMyOrders(@AuthUser() user: any): Promise<Order[]> {
   return this.orderService.findbyUserId(user._id);
 }