학습 목표
- JWT에 대한 이해
- JWT를 활용한 인증, 인가 구현
- 로그인, 회원가입 로직 이해
1. 회원가입 기능
- 회원가입 시 이메일, 패스워드를 받아서, DB에 이메일, 패스워드, 회원 가입 시간을 저장해야 한다.
- 유저에 대한 정보가 저장될 때, id(PK, primary key)도 같이 Auto-increment 형식으로 저장돼야 한다.
- 이메일에 반드시 @가 1개만 포함되어 있어야 한다.
- 이메일에 공백이 포함될 수 없다.
- 중복된 이메일이 존재할 수 없다.
- 패스워드에 공백이 포함될 수 없다.
- 패스워드는 8자 이상 15자 이하여야 한다.
- (비밀번호는 암호화하지 않고 그대로 저장한다. 암호화하는 건 뒤에서 구현하게 된다.)
2. 로그인 기능
- 로그인 시 이메일, 패스워드 값을 받는다.
- 로그인에 성공했을 때, JWT를 활용해 Access Token 값을 응답해야 한다.
- JWT의 payload에는 사용자의 id(PK, primary key)가 반드시 담겨있어야 한다.
3. 내 정보 조회 기능
- 사용자가 요청을 보낼 때 Header에 JWT 토큰을 넘기도록 한다.
- Header에 JWT 토큰이 담겨있지 않다면 에러로 응답한다.
- Header에 담겨있는 JWT 토큰이 올바르지 않거나 조작되었다면 에러로 응답한다.
- Header에 담겨있는 JWT 토큰의 만료기간이 지났다면 에러로 응답한다.
- Haeder에 담겨있는 JWT 토큰이 올바르다면, JWT 토큰의 payload에 담겨있는 사용자의 id(PK, primary key)를 활용해라.
- 응답값에는 id(PK, primary key), 이메일, 회원 가입 시간이 포함되어야 한다.
- 응답값에는 패스워드가 포함되면 안 된다.
Tip : ‘회원가입 기능’ → ‘로그인 기능’ → ‘내 정보 조회 기능’ 순서로 구현해라!
우선 위의 기능들을 구현하기 위해 User moduel을 만든다.
nest g mo users
nest g s users
nest g co users
기본적인 컨트롤러틀을 생성.
회원가입에 필요한 인자 dto 및 nest에 의존성 주입을 맡기기 위해 생성자 생성
서비스 틀 작성
CREATE TABLE `User` (
`userIdx` INT NOT NULL AUTO_INCREMENT,
`id` INT NULL,
`nickName` VARCHAR(20) NULL,
`phone` CHAR(11) NULL,
`password` VARCHAR(300) NULL,
PRIMARY KEY (`userIdx`)
);
DB에 위와 같은 쿼리를 날려 User 테이블을 추가 한다.
DB에 해당 스키마가 생성된것을 확인.
entity코드를추가
typeorm 연결하기
$ npm install --save @nestjs/typeorm typeorm mysql2
appmodule에 User entity를 추가한다. (synchronize는 개발환경일시만 true)
회원가입 만들기
레포지토리 의존성 주입.
미션에 필요한 컬럼을 확인 못하여 id를 email로 변경하였다.
회원가입 서비스 로직 작성
서버를 돌리니 에러가 떴다.
Userservice에서 UserRepository를 인젝션하는데 module에서 인젝션을 해주지 않아서 발생한 에러 이다.
usermodue에 User엔티티 import
bcrypt 모듈이 default export를 제공하지 않기 때문에 위의 import로 가져오는데 문제가 생겨 아래 코드로 수정하였따.
import * as bcrypt from "bcrypt";
닉네임과 phone이 저장이안되는 문제 발생. ==> 우선 차후 확인해 보자 !
CREATE TABLE `User` (
`userIdx` INT PRIMARY KEY AUTO_INCREMENT,
`email` VARCHAR(255) NULL,
`nickName` VARCHAR(255) NULL,
`phone` VARCHAR(255) NULL,
`password` VARCHAR(255) NULL,
`signupTime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
하지만 nickname과 phone에서 [QueryFailedError: Field 'nickName' doesn't have a default value] 에러가 떠서
이렇게 추가 하였다.
@Column() nickName: string | null;를 @Column('varchar', { name: 'nickName', nullable: true, length: 20 }) nickName: string | null;로 수정하니 해결
다른 값들은 안뜨는데 왜 저 두값만 뜰지가 의문이다 우선 이후 미션들을 진행하며 차차 알아가 보고자 한다.
우선 원인은 데이터베이스 테이블의 nickName 열에 대한 설정과 TypeORM의 엔티티 클래스의 nickName 속성의 설정 간에 불일치.
==> typeorm과 nest database 부분의 공식문서를 참조하자
다시 !
typeorm-model-generator를 사용하여 DB 로부터 entity 생성
npm i typeorm-model-generator -D
npx typeorm-model-generator -h localhost -d nest_board -p 3306 -u root -x 0000 -e mysql -o ./mymodel
==> 앞으로도직접 타이핑 하지말고 typeorm-model-generator사용해서 entity를 생성하자 !
==> 컨트롤러에서 async await를 안써서 postman에 응답이 안갔는데 질문!
==> promise 안에서는 에러가 아닌 경고로 뜬다. ==> 컨트롤러로 전달이 안된다.
reqest life cycle (+미들웨어도 익셉션 필터에서 에러처리가 된다.)
JWT로그인 구현
Guard는 컨트롤러에 접근하기전에 권한!!이 있는지 데이터가 제대로있는지 확인
$ npm i @nestjs/passport passport passport-local
$ npm install --save @nestjs/jwt passport-jwt
$ npm install --save-dev @types/passport-jwt
$ nest g module auth
$ nest g controller auth
$ nest g service auth
appmoduel에 imports된것을 확인
상속받은 authguard는 strategy를 자동으로 실행해주는 기능이 있다.
그리고 strategy에서 바로 validate를 실행
strategy생성 및 authmodule에서 impoorts할것도 가져온다.
순환 참조 모듈로 인해 에러가 발생 하였다.
user모듈과 auth모듈에서 서로를 참조하기 때문이다.
user모듈과 auth모듈에 각각 순환 참조를 해겨 ㄹ하기 위해 forwardRef함수를 import를 해주었다.
forwardRef(() => UsersModule)
exports: [AuthModule, AuthService],
모든 요청에 유저의 정보를 확인하기 위해 authservice에서 jwt 생성자 추가
service와strategy를 사용하기 위해 provider에 넣어줘야한다.
또한 다른 모듈에서 사용하기 위해 exports도 시켜줘야한다.
로그인 성공시 토큰 받아오기 성공
@UseGuard를 사용하여 요청안에 유저 정보를 넣어준다.
그러면 콘솔에 user객체를 확인할 수 있다.
req.user로 확인하는 것이 아니라 user라는 파라미터로 가져오기 위해 커스텀 데코레이터를 이용해보자.
완료 !
인증된 유저만 게시물 보고 쓸수 있게 해보자.
post모듈에서 guard를 사용하기 위해서는 guard를 구현한 auth모듈을 import 시켜야한다.
컨트롤러전체에 guard처리를한다.
포스트맨에서 이제 인증된 유저(토큰을 보내야만)만 게시물 api를 사용할 수 있는것을 확인
이제 큼지막한 기능 구현은 끝났고 세부 유효성 검사 코드를 추가해 보자.
위 코드를 수정하여 password필드를 제외하고 가져왔다.
'외부활동 > JSCODE 서버[Nest]' 카테고리의 다른 글
3회차 API 서버 배포[ CORS세팅,에러처리] (0) | 2024.02.29 |
---|---|
2회차 익명 게시판 서비스 [에러 및 부족한 개념 채우기] (2) | 2024.02.29 |
2회차 익명 게시판 서비스 [API문서 Swagger 만들기] (0) | 2024.02.29 |
2회차 익명 게시판 서비스 [유효성 검사, 예외처리] (0) | 2024.02.29 |
2회차 익명 게시판 서비스 [정렬, 검색, 개수제한] (0) | 2024.02.29 |