JsonWebTokenError: jwt must be provided nest JS

JsonWebTokenError: jwt must be provided nest JS

我正在尝试使用 nest.JS 从我的本地后端传递一些数据,登录成功并且 jwt 令牌显示在 cookie 中,但错误显示:

[Nest] 39  - 02/22/2022, 9:50:59 AM   ERROR [ExceptionsHandler] jwt must be provided
nest-admin-backend-1  | JsonWebTokenError: jwt must be provided
nest-admin-backend-1  |     at Object.module.exports [as verify] (/app/node_modules/jsonwebtoken/verify.js:53:17)
nest-admin-backend-1  |     at /app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:53
nest-admin-backend-1  |     at new Promise (<anonymous>)
nest-admin-backend-1  |     at JwtService.verifyAsync (/app/node_modules/@nestjs/jwt/dist/jwt.service.js:42:16)
nest-admin-backend-1  |     at AuthService.userId (/app/src/auth/auth.service.ts:16:44)
nest-admin-backend-1  |     at AuthController.user (/app/src/auth/auth.controller.ts:68:43)
nest-admin-backend-1  |     at /app/node_modules/@nestjs/core/router/router-execution-context.js:38:29
nest-admin-backend-1  |     at processTicksAndRejections (node:internal/process/task_queues:93:5

至于代码,没有任何错误,我正在按照教程进行操作,但它不起作用。

如果我按照错误消息进行操作,它会在我的 auth.service 和 auth.controller 文件中说明错误,所以这是我的文件片段:

Auth.controller

export class AuthController {

    constructor(
        private userService: UserService,
        private jwtService: JwtService,
        private authService: AuthService,
    ) {
    }

    @Post('register')
    async register(@Body() body: RegisterDto) {
        if (body.password !== body.password_confirm) {
            throw new BadRequestException('Password do not match!');
        }

        const hashed = await bcrypt.hash(body.password, 12);

        { }

        return this.userService.create({
            firstName: body.firstName,
            lastName: body.lastName,
            email: body.email,
            password: hashed,
            role: { id: 1 }
        });
    }

    @Post('login')
    async login(
        @Body('email') email: string,
        @Body('password') password: string,
        @Res({ passthrough: true }) response: Response,
    ) {
        const user = await this.userService.findOne({ email });

        if (!user) {
            throw new NotFoundException('User not found!');
        }

        if (!await bcrypt.compare(password, (await user).password)) {
            throw new BadRequestException('Invalid password!');
        }

        // Generate JWT

        const jwt = await this.jwtService.signAsync({ id: user.id })

        response.cookie('jwt', jwt, { httpOnly: true });
        return user;
    }

    @UseGuards(AuthGuard) // This is a custom guard
    // Authenticate user and generate JWT
    @Get('user')
    async user(@Req() request: Request) {
        const id = await this.authService.userId(request);

        // Get user from the database
        return this.userService.findOne({ id });
    }

    @UseGuards(AuthGuard) // Check if user is authenticated
    @Post('logout')
    async logout(@Res({ passthrough: true }) response: Response) {
        response.clearCookie('jwt');

        return {
            message: 'Logged out successfully',
        }
    }
}

Auth.service

export class AuthService {

    constructor(private jwtService: JwtService) {

    }

    async userId(request: Request): Promise<number> {
        const cookie = request['jwt'];

        // Get data from the Cookie
        const data = await this.jwtService.verifyAsync(cookie);

        // Get user from the database
        return data['id'];
    }
}

即使我已经登录,我也无法访问邮递员的 localhost:8000/api/user。知道如何解决吗?

Cookie 是 HTTP 服务器和浏览器之间的协议,因此 Postman 和后端不能只登录并发送 cookie header。

要允许您的 API 服务器识别应用程序(移动、桌面和服务器),需要引入一种额外的方式来发送 JWT。

除了 Cookies 之外,还允许将 JWT 作为 HTTP header 发送。使用 Authorization header 作为发送 JWT 的辅助方法。

要做到这一点,您需要:

  1. 将您的 /login 修改为 return JWT 作为纯文本(而不是用户)
    @Post('login')
    async login(
        @Body('email') email: string,
        @Body('password') password: string,
        @Res({ passthrough: true }) response: Response,
    ) {
        const user = await this.userService.findOne({ email });
        
        ...

        // Generate JWT
        const jwt = await this.jwtService.signAsync({ id: user.id })

        response.cookie('jwt', jwt, { httpOnly: true }); // <-- for browsers
        return jwt;  // <--- for applications
    }

现在应用程序有责任根据子序列请求存储和发送 JWT(使用 Authorization header)

  1. 更新您的 AuthGuard 以检查 cookieAuthorization header 中的 JWT。