Files
nestapp/src/modules/user/guards/jwt.auth.guard.ts
T
2025-06-22 19:16:23 +08:00

83 lines
2.4 KiB
TypeScript

import { ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { isNil } from 'lodash';
import { ExtractJwt } from 'passport-jwt';
import { TokenService } from '@/modules/user/services/token.service';
import { ALLOW_GUEST } from '../constants';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
constructor(
protected ref: Reflector,
protected tokenService: TokenService,
) {
super();
}
async canActivate(context: ExecutionContext) {
const allowGuest = this.ref.getAllAndOverride<boolean>(ALLOW_GUEST, [
context.getHandler(),
context.getClass(),
]);
if (allowGuest) {
return true;
}
const request = this.getRequest(context);
const requestToken = ExtractJwt.fromAuthHeaderAsBearerToken()(request);
if (isNil(requestToken)) {
throw new UnauthorizedException();
}
const accessToken = await this.tokenService.checkAccessToken(requestToken);
if (isNil(accessToken)) {
throw new UnauthorizedException();
}
try {
return (await super.canActivate(context)) as boolean;
} catch {
const response = this.getResponse(context);
const token = await this.tokenService.refreshToken(accessToken, response);
if (isNil(token)) {
throw new UnauthorizedException();
}
if (token.accessToken) {
request.headers.authorization = `Bearer ${token.accessToken.value}`;
}
return (await super.canActivate(context)) as boolean;
}
}
/**
* 自动请求处理
* 如果请求中有错误则抛出错误
* 如果请求中没有用户信息则抛出401异常
* @param err
* @param user
* @param _info
*/
handleRequest(err: any, user: any, _info: any) {
if (err || isNil(user)) {
if (isNil(user)) {
throw new UnauthorizedException();
}
throw err;
}
return user;
}
getRequest(context: ExecutionContext) {
return context.switchToHttp().getRequest();
}
getResponse(context: ExecutionContext) {
return context.switchToHttp().getResponse();
}
}