react&node.js 개발 - 로그인하면서 JWT 토큰 발급받고 유저 정보 알아내기
1. 비밀 키 생성
백엔드에 config.js 파일 작성
다음과 같이 secret key를 작성
JWT 토큰 검증시 해싱에서 사용할 키라고함
//backend//config.js
//jwt verification secret key
module.exports = {
'secret':'대혁이다'
}
2. 서버에 secret key 세팅
서버에 작성한 config 파일을 불러오고 secret key를 다음과 같이 세팅
//backend/server.js
// set the secret key variable for jwt
const config = require('./config')
app.set('jwt-secret', config.secret)
3. 로그인 api 작성
$npm install jsonwebtoken으로 모듈 설치
//backend/server.js
//login api
const jwt = require('jsonwebtoken');
app.post('/api/login',(req,res) => {
console.log(req.body)
const key = req.app.get('jwt-secret')
User.findAll({
where: { [Op.and]: [{email:req.body.email, password:req.body.password}]}
})
.then(result => {
if (result[0]){
const user_id = String(result[0].id)
let token = jwt.sign(
{
type:"JWT",
username: result[0].username
},
key,
{
expiresIn: "1d",
issuer: "IGoAT",
jwtid: user_id,
}
)
return res.send({
result,
jwt:token,
})} else {
return res.send({
result,
jwt:''})
}
})
.catch(err => {
throw err;
})
})
세팅한 key를 req.app.get('jwt-secret')로 받아오고
클라이언트에서 받아온 req에서 아이디, 비밀번호를 가져와 User 테이블에서 해당 정보가 존재하는지 검증
그러면 result가 객체가 1개 있는 배열로 들어오는데
result[0]가 존재한다면 해당하는 유저 데이터가 존재하는 것이고
존재하지 않는다면 해당하는 유저 데이터가 존재하지 않는다는 뜻이다
4. jwt 토큰 발급받는 함수
위 로그인 api에서 JWT 토큰 발급받는 부분이 아래와 같이 생긴듯
if (result[0]){
const user_id = String(result[0].id)
let token = jwt.sign(
{
type:"JWT",
username: result[0].username
},
key,
{
expiresIn: "1d",
issuer: "IGoAT",
jwtid: user_id,
}
)
깃허브 옵션 보면 jwt.sign(payload, secret, option,...)으로 구성된다
payload에는 토큰에 넣을 정보들을 포함하는데 여러가지가 있고 복잡하다..
여기서는 유저이름만 넣었고
secret에는 앞에서 세팅했던 해싱 알고리즘에 사용할 key
option에는 여러가지 설정할 수 있는데
expireIn은 토큰 유효기한으로 1d는 하루겠지.. 10h하면 10시간일듯
issuer은 토큰 발급자
jwtid는 토큰을 발급받은 유저의 아이디를 나타낸다. 이거는 나중에 사용할려면 웬만하면 작성해줄 필요가 있다
아무튼 이렇게 토큰 발급받는 api작성하고 실제 로그인하면 jwt 토큰 발급받는 것을 확인할 수 있다
5. 로그인 비밀번호 암호화
로그인할때 비밀번호를 암호화해서 서버에 전달해줄 필요가 있다
리액트에서 crypto 모듈을 이용하면 가능한데, 내장된 모듈이라 설치할 필요는 없는 것 같다
유저가 입력한 비밀번호 password를 받아와 crypto.createHash().update().digest()로 암호화시킬 수 있다
createHash 안에는 암호화알고리즘이 들어가고 sha256, sha512 등이 있다.
update에는 유저가 입력한 비밀번호
digest에는 해쉬 표기법으로 인코딩 방식을 정하는 건데 base64, hex 등이 있나봄
digest는 어떤걸 쓰느냐에 따라 암호화 결과 길이가 달라지나봐
//hash password
//password: 유저가 입력한 비밀번호
//hashPassword: 암호화된 비밀번호
let hashPassword = ''
try {
hashPassword = crypto
.createHash('sha512')
.update(password)
.digest('hex')
} catch (e) {
return;
}
6. crypto 사용중 에러
crypto 사용중에 에러가 난다면...
대충 아래와 같은 에러가 날 수가 있음
Module not found: Error: Can't resolve 'crypto' in '/home/borislav/Desktop/bobbyhadz-rest/bobbyhadz-react/node_modules/cookie-signature'
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }
그러면 npm install crypto-browserify로 모듈 설치하고
frontend/config/webpack.config.js에서 resolve를 찾아본다
그리고 fallback을 찾아서 이렇게 써주면 되더라
물론 crypto-browserify를 작성하고, 다시 에러나서 stream-browserify, buffer도 설치하라고 나와서
그것도 아래와 같이 작성했음
7. jwt 토큰 해독하기
jwt 토큰을 해독해서 유저의 정보를 알아낼 수 있다
jwtDecode 함수를 이용하면 jwt 토큰을 해석해줌
import jwtDecode from "jwt-decode";
export class jwtUtils {
// 토큰 유효성 검사
static isAuth(token) {
if (!token) {
return false;
}
const decoded = jwtDecode(token);
if (decoded.exp > new Date().getTime() / 1000) {
return true;
} else {
return false;
}
}
// 토큰에서 유저 id 가져오기
static getId(token) {
const decoded = jwtDecode(token)
console.log(decoded)
return decoded.jti;
}
}
실제 사용해보면 이런식으로 나옴
jwt 토큰 발급하는 함수 작성할때 옵션에 넣었던 정보들이 들어가있다
옵션에 쓰지 않으면 나오지 않는다
예를 들어 jwtid를 작성하지 않으면 jti 값이 나오지 않아
if (result[0]){
const user_id = String(result[0].id)
let token = jwt.sign(
{
type:"JWT",
username: result[0].username
},
key,
{
expiresIn: "1d",
issuer: "IGoAT",
jwtid: user_id,
}
)
iss는 토큰 발급자, iat는 토큰 발급시간, exp는 만기시간,
jti는 고유식별자, 여기서는 유저 id값을 넣어서 해독해서 유저 id를 알아낼 수 있도록 했음
참조
auth0/node-jsonwebtoken: JsonWebToken implementation for node.js http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html (github.com)
[JWT] JSON Web Token 소개 및 구조 | VELOPERT.LOG
Node.js / crypto module(단방향 암호화) / 해시 생성 (tistory.com)
[NodeJS] crypto를 이용한 단방향 암호화(해시 함수) 만들기 (tistory.com)
Module not found: Error: Can't resolve 'crypto' [Solved] | bobbyhadz
'프로그래밍 > node.js' 카테고리의 다른 글
react&node.js 개발 -python-shell이용해서 서버에서 python 프로그램 실행시키기- (0) | 2023.01.24 |
---|---|
react&node.js 개발 -image 데이터 서버에 저장하는 방법 배우기 (0) | 2023.01.22 |
node.js 프로그래밍에서 axios 504에러날때 시도할부분 (0) | 2023.01.19 |
react와 express 서버 연동 익히기 9편 -DB 데이터 삭제하기- (0) | 2023.01.18 |
react와 express 서버 연동 익히기 8편 -DB 데이터 수정하기- (0) | 2023.01.18 |