撰于 阅读 380

nestjs中decorators与guard配合

guard实现了CanActivate
方法:canActivate 返回true 验证通过

以下是一个jwt验证模块

ps:
decorators - requireLogin.ts

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

export const IS_REQUIRE_LOGIN_KEY = 'requireLogin';

export const requireLogin = () => SetMetadata(IS_REQUIRE_LOGIN_KEY, true);

guard - user-auth.guard.ts

import {
    CanActivate,
    ExecutionContext,
    Injectable,
    UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Reflector } from '@nestjs/core';
import { IS_REQUIRE_LOGIN_KEY } from '../decorators/requireLogin';
import { Observable } from 'rxjs';

@Injectable()
export class UserGuard implements CanActivate {
    constructor(private jwtService: JwtService, private reflector: Reflector) { }

    canActivate(
        context: ExecutionContext
    ): boolean | Promise<boolean> | Observable<boolean> {
        const request = context.switchToHttp().getRequest();
        // 获取是否需要鉴权
        const requireLogin = this.reflector.getAllAndOverride(IS_REQUIRE_LOGIN_KEY, [
            context.getClass(),
            context.getHandler()
        ]);
        const authorization = request.headers.authorization;
        // 没有则放行,公共接口(不需要登录)
        if (!requireLogin) {
            return true;
        }
        // 需要鉴权,切没有token
        if (!authorization) {
            throw new UnauthorizedException("用户未登录");
        }
        try {
            const token = authorization.split(" ")[1];
            const data = this.jwtService.verify(token);
            // userInfo中包含登录成功的用户信息
            let { iat, exp, ...userInfo } = data;
            request.userInfo = {
                ...userInfo,
            };
            return true;
        } catch (error) {
            throw new UnauthorizedException("用户未登录");
        }
    }
}

通过方法this.reflector.getAllAndOverride获取是否需要拦截,如果没有获取到,说明没有该装饰器,为公共接口,直接放行,否则进行一些业务处理...