0

我正在使用 JWT 和 NestJS 构建这个 API。这是一个移动应用程序的 API,所以我需要不断刷新 JWT 令牌。这个想法是检查传入的令牌请求,如果令牌过期,JWT 会抛出一个错误消息说令牌过期。如果是这种情况,令牌将被刷新,如果是另一个错误,它将引发错误。

我还有一个 GetUser 装饰器,它可以从 HttpRequest 返回用户,但现在我使用的是自定义 AuthGuard,我无法让它工作。有小费吗?

AuthGuard.ts

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { LoginService } from 'src/users/login.service';

@Injectable()

export class AuthGuard implements CanActivate {

    constructor(
        private loginService: LoginService,
        private jwtService: JwtService
    ) {}

    async canActivate( context: ExecutionContext ) {
        const request = context.switchToHttp().getRequest();
        const { headers } = request;

        const headerString = headers.authorization.split(' ');

        const currentToken = await this.loginService.validateToken(headerString[1]);

        return currentToken ? true : false;

    }

}

登录服务.ts

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

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

    async validateToken(token: string): Promise<any> {
        try {
            const verifiedToken = await this.jwtService.verify(token, { secret: process.env.JWT_SECRET });
            return verifiedToken;
        } catch (error) {
            if (error.message === 'jwt expired' ) {
                const newToken = await this.refreshToken(token);
                return newToken;
            } else {
                throw new UnauthorizedException();
            }
        }
    }

    async refreshToken(token: string | any ): Promise<any> {
        const decodedToken = await this.jwtService.decode(token) as any;
        const { email, id } = decodedToken;;
        const payload = { email, id };
        const options: JwtSignOptions = {
            secret: process.env.JWT_SECRET,
            expiresIn: '2w'
        };
        const accessToken = await this.jwtService.sign(payload, options);
        return { accessToken };
    }
}

用户装饰器.ts

import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { User } from "./user.entity";

export const GetUser = createParamDecorator( (data, ctx: ExecutionContext): User => {
    const req = ctx.switchToHttp().getRequest();
    return req.user;
});

任何帮助将不胜感激!谢谢

4

1 回答 1

0

如果令牌有效,则解码令牌并将用户有效负载添加到 canActivate 方法中的请求对象,然后再发送 true 或 false。GetUser 装饰器从请求中获取用户对象。

例子:

// AuthGuard.ts

async canActivate( context: ExecutionContext ) {

....
....

request.user = currenToken // decoded token returns payload anyway
return true
}

您不必返回 false,因为如果令牌无效,则会引发未经授权的错误,并且异常过滤器会处理该问题

于 2020-11-22T15:25:09.603 回答