인증 기능


지금까지는 보드 모듈.
AuthModule 에서 인증 관련 기능.

보드 모듈 만들었던 것 처럼 CLI 이용해 모듈, 컨트롤러, 서비스 생성.

> nest g module auth : auth 모듈 생성
> nest g controller auth --no-spec : auth 컨트롤러 생성
> nest g service auth --no-spec : auth 서비스 생성

  • User위한 Entity 생성

유저에 대한 인증 하는 것이니, 유저 필요.
유저 데이터 위한 유저 entity 생성. (유저 데이터 어떻게 생겼는지, 형식 지정. 클래스 처럼)
user / user.entity.ts

  • Repository 생성

user entity를 db와 관련된 로직 처리하는 곳. (생성, 수정, 삭제 등)
user / user.repository.ts

생성된 User Repository 다른 곳에서도 사용하기 위해 auth module에서 imports 안에 넣어줌.

User Repository를 서비스 안에서 사용하기 위해 넣어줌. (Inject)

컨트롤러에서 서비스 사용 위해 서비스 inject.

  • 회원가입 기능 구현

entity는 db와, dto는 view와 통신 (?)
https://gmlwjd9405.github.io/2018/12/25/difference-dao-dto-entity.html

dto

repository

리포지토리에서 만든것 서비스에서 가져오기

컨트롤러

pgadmin 에서 확인

  • 유저 데이터 유효성 체크

유저 생성 시 원하는 이름의 길이, pw 조건 체크하기
Class-validator 사용

ValidationPipe 사용
요청이 컨트롤러에 있는 핸들러로 들어왔을 때 Dto에 있는 유효성 조건에 맞게 체크 해주려면 pipe 넣어야 함. (pipe는 유효성 체크)

핸들러 실행되기 전에 pipe가 먼저 유효성에 잘 맞는지 확인함.

컨트롤러

  • 유저 이름은 유일한 값

두가지 방법.
1. repository에서 findOne으로 확인 후 없으면 데이터 저장. db 처리 2번 함.
2. db레벨에서 에러 던지기. 한번에 해결. V

entity파일에서 @Unique(['username'])

이미 있는 username 입력 시 500, internal server error 나옴.

repository에서 try catch 구문으로 잡아야 함. 아니면 그냥 controller 레벨로 가서 500 에러 던져버림.

  • 비밀번호 암호화

지금까지는 비밀번호가 그대로 db에 저장됨. (최악)
비밀번호를 암호화 해 저장하자.

bcrypt 모듈 사용
npm i bcryptjs --save

=> hash + salt 사용
salt + 비밀번호를 해시해서 저장함. 유저마다 유니크한 salt

repository

둘다 같은 비밀번호로 생성했지만 db에 저장되는 hashedPassword 값은 다르다.

  • 로그인 구현

서비스 -> 컨트롤러
bcrypt.compare(pw, 해시된 pw)

  • jWT

로그인 시 유저마다 고유 토큰 생성 -> JWT
Jason Web Token
디지털 서명.

정보 안전하게 전할 때 혹은 유저 권한 체크할 때 유용한 모듈.

헤더: 토큰에 대한 메타 데이터 포함. (타입, 해싱 알고리즘..)

payload: 유저 정보, 만료 기간, 주제..

verify signature: 이 토큰이 위조 되지 않았는지 확인할 수 있는 부분. 헤더 + 페이로드 + 비밀 키 사용해 생성 (해시 알고리즘으로 합침).

JWT 사용 흐름

유저가 로그인 시 토큰이 생성 됨.

  • JWT 이용해 토큰 생성하기

애플리케이션에 모듈 import

auth 모듈

  • 로그인 성공 시 JWT 이용해 토큰 생성

모듈에서 jwt 등록했기 때문에 서비스에서 주입해 사용 가능.

  • 로그인 과정

  1. 클라이언트가 서버에 요청 보내면
  2. 서버가 받은 유저 정보 토대로 토큰 생성
  3. 리스폰스에 토큰 넣어서 유저한테 보냄
  4. 받은 토큰 저장해둠. (쿠키, 로컬 스토리지 등)
  5. 다시 요청 보낼 때 토큰 헤더 안에 넣어서 보냄
  6. 서버에서 토큰 유효한지 확인

유효하다면(verify signature 확인) 토큰 안에 들어있는 payload(여기서는 username) 이용해서 그에 맞는 유저를 db에서 찾음. 있으면 그 정보 다 가져옴. 없으면 에러.

payload에 맞는 유저 있다면 리퀘스트 객체에 넣어서 보냄.

위 과정 구현 위해 jwt.strategy.ts 생성.

사용위해 모듈에 넣기

  • req 안에 유저 정보(유저 객체) 들어가게 하는 방법

UseGuard 사용.
Guards: 인증 미들웨어.

커스텀 데코레이터 사용 안하면

test(@Req()) req {
  console.log(req.user); // req.user 해야 유저 객체 얻을 수 있음
}

커스텀 데코레이터 사용하면 req.user 아닌 바로 user 라는 파라미터로 가져올 수 있음.

get-user.decorator.ts

좋은 웹페이지 즐겨찾기