728x90
- Middleware란?
라우트 핸들러가 실행되기 전에 실행된다. Request와 Response 객체에 접근 할 수 있다.
- 자유롭게 코드 실행
- 요청과 응답 객체를 변경
- 요청 응답 사이클 중단
- 다음 미들웨어 실행
- 미들웨어 선언법
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request ...');
next();
}
}
- 미들웨어 적용법 (app.module.ts)
- 간단
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('cats');
}
}
- 세부적
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes({ path: 'cats', method: RequestMethod.GET });
}
}
.forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
ab 아무거 cd, 그냥 *은 모든
- 제외
consumer
.apply(LoggerMiddleware)
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
'cats/(.*)',
)
.forRoutes(CatsController);
forRoutes => 어떤 라우트에 적용할 지
'cats/(.*)' => 이렇게 string으로도 가능
- 순차적 = 여러개
consumer.apply(cors(), helmet(), logger()).forRoutes(CatsController);
- 글로벌 적용 (main.ts)
const app = await NestFactory.create(AppModule);
app.use(Logger);
await app.listen(3000);
- codefactory 강의에서 작성한 Bearer 토큰 검증 예시
실제로 뒤에 guard에서 검증하면 될 것이기 때문에 사실 아래 코드는 그냥 사용 예시로 보는게 좋을 듯.
jwtService의 경우 authModule에서 jwtModule exports 필요
import {
BadRequestException,
Injectable,
NestMiddleware,
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { NextFunction, Request, Response } from 'express';
import { envKeys } from 'src/common/const/env.const';
@Injectable()
export class BearerTokenMiddleware implements NestMiddleware {
constructor(
private readonly jwtService: JwtService,
private readonly configService: ConfigService,
) {}
async use(req: Request, res: Response, next: NextFunction) {
const authHeader = req.headers.authorization;
if (!authHeader) return next();
const token = this.validateBeaerToken(authHeader);
try {
const decodedPayload = this.jwtService.decode(token);
if (decodedPayload.type !== 'refresh' && decodedPayload.type !== 'access')
throw new UnauthorizedException('잘못된 토큰입니다!');
const secretKey =
decodedPayload.type === 'refresh'
? envKeys.refreshTokenSecret
: envKeys.accessTokenSecret;
const payload = await this.jwtService.verifyAsync(token, {
secret: this.configService.get<string>(secretKey),
});
req.user = payload;
next();
} catch (e) {
if (e.name === 'TokenExpiredError')
throw new UnauthorizedException('토큰이 만료됐습니다.');
next();
}
}
validateBeaerToken(rawToken: string) {
const basicSplit = rawToken.split(' ');
if (basicSplit.length !== 2)
throw new BadRequestException('토큰 포맷이 잘못됐습니다!');
const [bearer, token] = basicSplit;
if (bearer.toLowerCase() !== 'bearer')
throw new BadRequestException('토큰 포맷이 잘못됐습니다!');
return token;
}
}
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(BearerTokenMiddleware)
.exclude(
{
path: 'auth/login',
method: RequestMethod.POST,
},
{ path: 'auth/register', method: RequestMethod.POST },
)
.forRoutes('*');
}
}
https://fastcampus.co.kr/classroom/239666
커리어 성장을 위한 최고의 실무교육 아카데미 | 패스트캠퍼스
성인 교육 서비스 기업, 패스트캠퍼스는 개인과 조직의 실질적인 '업(業)'의 성장을 돕고자 모든 종류의 교육 콘텐츠 서비스를 제공하는 대한민국 No. 1 교육 서비스 회사입니다.
fastcampus.co.kr
728x90
'코딩 > Nest.js' 카테고리의 다른 글
RBAC (Role Based Access Control) (0) | 2024.10.23 |
---|---|
Guard 실사용적 (0) | 2024.10.23 |
passport (0) | 2024.10.22 |
JWT (0) | 2024.10.22 |
Mapped Type (0) | 2024.10.22 |