일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 라우터 분리
- 블록 만들기
- javascript기초
- buffer.from
- useContext
- Uncaught Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
- 세션으로 로그인 구현
- FormData()
- JWT 로그인 기능 구현
- express router
- express session
- cookie-parser 만들어보기
- mysql wsl
- css기초
- OAuth 카카오
- next 매개변수
- express실행
- JWT 만들어보기
- JWT 하드코딩
- 아이디 중복체크기능
- 라우터와 미들웨어
- nodejs파일업로드
- 라우터미들웨어 분리
- 시퀄라이즈 기본설정
- express.static
- node.js path
- ws 라이브러리
- 비동기파일업로드
- useEffect clean up
- 라우트 매개변수
- Today
- Total
즐코
JWT로 로그인 기능 구현해보기 본문
저번 미니 프로젝트 복습 겸 사용자계정을 DB에서 당겨오는 방식으로 JWT 로그인 기능 구현을 연습해보았다.
사실 router 분리를 해야하지만 로그인 기능만 구현할 거니까 server.js 파일에 다 때려박았다.
이번엔 async await를 써보자고 마음먹었다.. 우선 써보기전에 원래 했던대로 콜백지옥을 만들어보앗다.
pool.getConnection의 인자로 콜백함수가 들어가고,
conn.query에도 3번째 인자로 콜백함수가 들어가니 그안에서 if문까지 써버리면 엄청난 depth가 생긴다.
특히, pool과의 connection을 다시 return해주는 conn.release()를 어디 괄호뒤에 써야할지 찾는 것도 힘들다.
그래서 async, await으로 바꿔보았다.
어떻게 바꿀지 감이 안잡혀서 다른 팀의 깃헙을 참고해서 공부했다.
https://github.com/green-kong/team6_login_board
1. pool 생성하기
우선, mysql이 아니라 promise를 지원해주는 mysql2 라는 모듈이 필요해서
npm install mysql2 또는 yarn add mysql2를 해준다.
그리고 불러올때는, const mysql = require('mysql2')가 아니라,
const mysql = require('mysql2/promise') 이런식으로 가져온다. db.js에서 따로 pool을 생성해주고 내보낸다.
2. pool 가져와서 async, await으로 server.js 파일 작성
async를 logincheck라는 함수앞에 붙여서 promise 를 반환하게끔 만들어준다.
await은 async 함수 안에서만 쓸 수 있는데, promise.then과 비슷한 역할이다. 말 그대로 기다린다 라는 뜻,
promise 객체인 pool.getConnection((err,conn)=>{})의 결과값을 변수 conn에 담아줬다.
const conn = await pool.getConnection()
쿼리문으로 데이터를 가져오는 conn.query(SQL.checkLogin,param,(err,result)=>{})의 결과값도 변수 result에 담아줌
const [ result ] = await conn.query(SQL.checkLogin, param)
이 때, result는 배열 안에 배열이 담겨져있는 형태 [[result]]로 나오므로 배열의 구조분해할당을 이용해서 배열을 한꺼풀 벗겨주었다.
if 문에서 아이디나 비번이 틀린 것을 잡아서 에러 처리를 하였고,
if (result.length === 0) throw new Error('아이디가 존재하지 않습니다')
그 이후구문은 else구문(아이디/비번 일치할때) 인데 else를 생략한 것이다.
JWT를 만들기 위해 DB에서 가져온 사용자의 데이터 result[0] 중에 공개해도 괜찮은 데이터를 payload 객체에 담아준다.
Token을 만드는 코드가 꽤 길어서 따로 빼주었다.
const token = createToken(payload)
그다음 토큰을 쿠키에 담아줄 차례이다.
res.setHeader('Set-cookie', `AccessToken=${token}; HttpOnly; Secure; Path=/;')
conn.release 는 로그인 실패/성공 여부에 상관없이 무조건 마지막에 처리해줘야 하므로, finally로 처리해줌
3. 토큰 만드는 함수 createToken 따로 뺌 (util/jwt.js)
해쉬화 과정에서 쓰이는 salt도 env 파일로 빼주었다.
근데 이때, jwt.js파일 상에서 require('dotenv').config() 했더니 .env파일에서 salt를 가져오지 못했다.
찾아보니 .env가 현재 경로가 아닌 다른 곳에 있을 경우엔 path, 경로를 명시해줘야했다.
config의 인자로 {path:"env파일 경로"} 를 넣어준다.
require('dotenv').config({path:"../.env"})
인코딩하는 과정도 반복해서 쓰이므로 따로 함수로 빼주었다.
signature만드는 과정도 함수로 따로 빼줌
토큰 만드는 코드,
인자로 들어가는 state에는 위에서 로그인에 성공한 사용자의 공개데이터를 payload에 넣는거다.
위의 토큰 생성 코드들은 이미 전 포스팅에서 정리했으므로 설명은 생략
이렇게 하면 로그인 시 AccessToken이 부여된다.
4. 토큰 검증하기 위한 미들웨어 auth 만들어주기
마지막으로,
그 이후에 누군가 payload쪽 내용을 조작하는 걸 방지하기 위해 auth라는 토큰 검증 미들웨어를 만들어주자.
1- 사용자의 쿠키에 있는 토큰의 헤더와 페이로드값을 이용해서 검증용 시그니처를 만들어주고
2- 사용자의 쿠키에 있는 토큰의 시그니처값과 검증용 시그니처를 비교하면 끝
예를 들어 관리자 페이지에서 auth 미들웨어를 넣는다면,
admin router 상에선 토큰 검증을 따로 하지않고 level 검사만 해줄수 있겠다.
'NodeJS' 카테고리의 다른 글
경로 / 내부 라이브러리 path (0) | 2022.03.16 |
---|---|
ajax (XHR/fetch/axios) 아이디 중복체크 살짝 구현해보기 (0) | 2022.03.07 |
crypto 모듈을 이용한 암호화 / JWT 만들어보기 (0) | 2022.03.04 |
JWT (ft.세션) (0) | 2022.03.03 |
http 요청,응답 동작 테스트 / curl 과 Postman (0) | 2022.02.15 |