TypeORM과 Guard를 활용한 인증 처리 이해하기
Guard는 Nest.js의 요청 처리 파이프라인 중 하나로, 특정 라우트 핸들러가 실행되기 전에 요청을 검사하고, 필요에 따라 요청을 거부하는 역할을 한다.
TypeORM과 Guard를 결합하면, 데이터베이스 엔티티에 대한 접근을 보안적으로 제어할 수 있다.
예를 들어, 특정 사용자가 요청한 데이터가 그 사용자에게 허용된 데이터인지를 확인하는 등의 인증 작업을 수행할 수 있다.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
// 인증 검사 로직
return validateRequest(request);
}
}
위 코드에서 AuthGuard는 CanActivate
인터페이스를 구현하며, canActivate
메소드를 통해 요청을 검사하고 인증 여부를 결정한다.
Guard는 canActivate
메소드를 통해 요청을 검사한다. 이 메소드는 true
또는 false
를 반환하며, false
를 반환하면 해당 요청은 거부된다. 이 메소드 내에서는 사용자 인증, 권한 검사 등의 로직을 수행할 수 있다.
Guard는 특정 라우트 핸들러 또는 컨트롤러 전체에 적용할 수 있다. 데코레이터 @UseGuards()
를 사용하여 Guard를 적용할 수 있다.
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard } from './auth.guard';
@Controller('cats')
@UseGuards(AuthGuard)
export class CatsController {
@Get()
findAll() {
// ...
}
}
Guard는 CanActivate
인터페이스를 구현하므로 커스터마이징이 가능하다.
예를 들어, 특정 권한이 있는 사용자만 허용하는 Guard, 특정 IP에서 오는 요청만 허용하는 Guard 등을 구현할 수 있다.
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
const hasRole = () => user.roles.some((role) => roles.includes(role));
return user && user.roles && hasRole();
}
}
위 코드는 RolesGuard
라는 새로운 Guard의 예시이며, 이 Guard는 특정 역할(role)을 가진 사용자만 허용한다. 이처럼 Guard를 커스터마이징하면, 보다 세밀한 인증 로직을 구현할 수 있다.