NestJS || Authentication

Alpha, Orderly·2023년 9월 19일
0

nestJS

목록 보기
6/8

Hashing

하는 방법

//해시테이블을 사용할수 없게 salt를 사용한다.
        const salt = randomBytes(8).toString('hex');
// salt를 포함해 해싱
        const hash = (await scrpyt(password, salt, 32)) as Buffer;
// 나중에 다시 해싱할수 있도록 salt를 포함해 저장한다.
        const result = salt + '.' + hash.toString('hex');

세션 설정하기

  • 라이브러리 설치하기
    • npm i cookie-session
    • npm i @types/cookie-session
  • main.ts 에 설정하기
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 쿠키 세션 사용하기
  // keys의 값을 사용해 쿠키를 암호화한다.
  app.use(cookieSession({
    keys: ['anythingyouwant']
  }))
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true
    })
  )
  await app.listen(3000);
}

세션에 값을 저장하는 예시

    @Get('/colors/:color')
    setColor(@Param('color') color:string, @Session() session: any) {
        session.color = color;
    }

    @Get('/colors')
    getColor(@Session() session: any) {
        return session.color;
    }
// session의 color에 값이 저장되고 조회된다.

로그인 확인

  • 특정 핸들러에 대해 로그인 되어 있지 않으면 거부
  • Guard로 부른다.

AuthGuard

class AuthGuard {
// 유저가 접근 가능할시 true 리턴
// 접근 불가능할시 false 리턴
	canActivate()
}
  • Guard를 만들어 전체 혹은 특정 컨트롤러 혹은 특정 핸들러에 적용 가능하다.

Guard 구현하기

export class AuthGuard implements CanActivate {
    // context : 들어온 요청
    canActivate(context: ExecutionContext) {
        const request = context.switchToHttp().getRequest();
        return request.session.userId;
    }
}
  • Guard 사용하기
    • UseGuards 데코레이터를 사용한다.
    @Get('/whoami')
    @UseGuards(AuthGuard)
    whoAmI(@CurrentUser() user: User) {
        return user;
    }

유저 확인

  • 현재 로그인한 유저가 누구인지 확인한다.
  • 인터셉터, 데코레이터를 통해 구현한다.

데코레이터

    @Get('/whoami')
    whoAmI(@CurrentUser() user: User) {
        return user;
    }
  • 위와 같은 custom decorator를 만들어 현재 로그인된 유저를 확인할 것이다.
  • 데코레이터는 이름.decorator.ts 로 짓는다.

데코레이터 구현

export const CurrentUser = createParamDecorator(
    // context : 요청의 정보를 담고 있다.
    // data : decorator의 소괄호에 들어가는 값
    // @CurrentUser(data) ...
    (data: never, context: ExecutionContext) => {
        // http request 가져오기
        const request = context.switchToHttp().getRequest();
        return request.currentUser;
    }
)
  • 데코레이터는 DI ( Injection ) 에 접근이 불가능해
    인터셉터를 같이 사용한다.

인터셉터 구현

  • request.currentUser 를 지정해 데코레이터에서 사용할수 있도록 한 것이다.
@Injectable()
export class CurrentUserInterceptor implements NestInterceptor {
    constructor(private usersService: UsersService) {}

    async intercept(context: ExecutionContext, handler: CallHandler) {
        const request = context.switchToHttp().getRequest();
        const { userId } = request.session || {};

        // userId가 있으면, currentUser으로 user를 초기화한다.
        if(userId) {
            const user = await this.usersService.findOne(userId);
            request.currentUser = user;
        }

        return handler.handle();
    }
}
  • 인터셉터 사용하기
    1. 컨트롤러단에 인터셉터 사용
    • 모듈에 provider로 추가하기
      @Module({
      imports: [TypeOrmModule.forFeature([User])],
      controllers: [UsersController],
      providers: [UsersService, AuthService, CurrentUserInterceptor]
      })
      export class UsersModule {}
    • 이후 UseInterceptors를 사용한다.
      @UseInterceptors(CurrentUserInterceptor)
      export class UsersController
    1. APP_INTERCEPTOR 사용하기 ( 모든 요청에 인터셉트 )
      @Module({
      imports: [TypeOrmModule.forFeature([User])],
      controllers: [UsersController],
      providers: [UsersService, AuthService, {
        provide: APP_INTERCEPTOR,
        useClass: CurrentUserInterceptor
      }]
      })
    • 프로바이더에 위와 같이 적용한다.
profile
만능 컴덕후 겸 번지 팬

0개의 댓글