-
[2019.05.10] JWT-Token 방식의 정보 인증 [사용법]개발 블로깅/기타 개념 2019. 5. 10. 22:24
사용자가 로그인 후, 유저 정보를 cookie,Session 방식이 아닌 token 방식으로 안전하게 관리하는 방법이 있다.
# token 방식의 특징
- 사용자 정보를 일일히 서버의 세션에 저장하지 않고, 사용자의 로컬에 저장.
- 사용자가 요청을 보낼 때마다 유저 정보 확인을 일일히 하지 않아도 됨.
- 웹 표준 기반 기술로써, 여러 환경에서 지원
이러한 토큰 방식을 사용하기 위해서는 JWT(Json Web Token) 기술을 사용한다.
# JWT 모듈 설치법
npm i -D jsonwebtoken
모듈을 설치한다.
# token 생성법
토큰을 생성하는 방법은 아래와 같다.
const jwt = require('jsonwebtoken'); var userInfo = {id: 1, username: 'inyong'}; var secretKey = 'SeCrEtKeYfOrHaShInG'; var options = {expiresIn: '7d', issuer: 'inyongTest', subject: 'userInfo'}; jwt.sign(userInfo, secretKey, options, function(err,token){ if(err) console.log(err); else console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJpbnlvbmciLCJpYXQiOjE1NTc0ODc2MjIsImV4cCI6MTU1ODA5MjQyMiwiaXNzIjoiaW55b25nVGVzdCIsInN1YiI6InVzZXJJbmZvIn0.idVKe2FVsmvwYBPFJc9vMXi4eZRfFJ6rwhiHIY4gZeo } )
jwt.sign() 함수에 들어가는 4가지 인자 설명
- userInfo : 아이디, 비밀번호 등 사용자 정보가 들어간 object이다. 형식은 상관없음.
- secretKey : 여러가지 복잡한 문자열로 되어있는 키.
- options: 토큰에 대한 여러가지 정보를 설정한다. expiresIn은 토큰 만료일, issuer, subject는 토큰에 대한 정보이다. 외에도 options가 더 있다.
- 4번째 인자로 들어가는 익명함수 : token 생성결과를 4번째 인자의 콜백함수로 받을 수 있으므로 넣어준 함수.
그럼 서버에서 사용자에게 요청을 받았을 시, token을 사용자에게 전달해주는 코드를 작성해보자.
예시)
const express = require("express"); const jwt = require('jsonwebtoken'); const app = express(); app.get('/',(req, res)=>{ const getToken = () => { return new Promise((resolve, reject) => { jwt.sign( { id: 1, username: 'inyong' // 유저 정보 }, 'SeCrEtKeYfOrHaShInG', // secrec Key { expiresIn: '7d', issuer: 'inyongTest', // options subject: 'userInfo' }, function(err,token){ if(err) reject(err) // callback else resolve(token) } ) }); } getToken().then(token =>{ res.send(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJpbnlvbmciLCJpYXQiOjE1NTc0ODc2MjIsImV4cCI6MTU1ODA5MjQyMiwiaXNzIjoiaW55b25nVGVzdCIsInN1YiI6InVzZXJJbmZvIn0.idVKe2FVsmvwYBPFJc9vMXi4eZRfFJ6rwhiHIY4gZeo }) }); var server = app.listen(3000, function(){ console.log("Express server has started on port 3000"); });
jwt.sign()함수는 비동기 함수이므로 Promise 처리를 해줘야 한다. 하단 부분에 res.send()로 사용자에게 토큰을 보내준다.
postMan을 이용해서 서버에게 요청을 보내보고, 응답으로 받은 토큰 값을 확인해보자.
JWT 홈페이지에서, 서버에게 받은 token값을 이용하여 인코딩 및 디코딩을 해볼 수 있다. token으로 나온 값을 Encoded 입력박스에 넣어보면, sign으로 넣었던 user 정보 및 options가 나오는 것을 확인할 수 있다.
# token 검증 방법
사용자는 서버에게서 토큰을 받은 후, 서버에게 요청을 보낼 때, request.Header에 토큰을 포함하여 요청을 보낸다.
그러면 서버는 사용자에게서 받은 토큰이 유효한 것인지 확인한다.
const secretKey = ''; // 아까 token 만들때 썼던 secretkey const router = (req, res) => { const token = req.headers['x-access-token'] || req.query.token; jwt.verify(token, secretKey, function(err, decoded){ console.log(err) // 유효하지 않은 토큰 console.log(decoded) // 유효한 토큰, 유저 정보 Object 반환 } }
jwt.verify()함수를 이용하여 토큰 유효성을 확인할 수 있다.
jwt.verify() 함수에 들어가는 매개변수 3개
- token: client에게서 받은 token
- secretkey : token 생성 시 사용했던 secretKey
- 3번째 인자로 들어간 익명함수 : 유효성 검사 결과를 처리할 callback 함수
예시)
client
var token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJpbnlvbmciLCJpYXQiOjE1NTc0OTE3NTYsImV4cCI6MTU1ODA5NjU1NiwiaXNzIjoiaW55b25nVGVzdCIsInN1YiI6InVzZXJJbmZvIn0.fpLkn6R6zjJXFq0i9xWpSmLrYmo-afyBjbPg2fJM25s'; fetch('http://localhost:3000', { method: 'POST', body: JSON.stringify({name:'inyong'}), headers: { 'content-type': 'text/json', 'x-access-token': token } }) .then(res => {return res.json()}) .then(res => { this.render(res); }); // client 단 서버 요청
server
//생략 ... const router = (req, res, next) => { const token = req.headers['x-access-token'] || req.query.token; // client에게서 받은 토큰 /* 토큰이 없으면 403 에러 응답 처리 */ if(!token){ return res.status(403).json({ success: false, message: 'not logged in' }); } /* 토큰 유효성 검사 */ const p = new Promise((resolve, reject) => { jwt.verify(token, req.app.get('jwt-secret'), (err,decoded) => { if(err) reject(err); else resolve(decoded); }) }); /* 유효하지 않은 토큰으로 403 에러 처리 */ const onError = (error) => { res.status(403).json({ success: false, message: error.message }) }; p.then((decoded)=>{ res.json(decoded); }).catch(onError); } app.post('/decoded', router);
참고로 secret 키와 토큰 검증 부분은 요청시 계속 사용되는 부분이다.
secret키는 .config파일로 따로 빼고, 토큰 검증 함수는 미들웨어로 빼서 사용하면 쉽게 사용할 수 있다.
앞으로 정보 관리방식은 JWT방식으로 처리하는 방식으로 쓰면 될 것 같다.
cookie와 Session 방식의 로그인 정보 인증을 해보지는 않았지만, 굳이 JWT 방식을 놔두고 써 볼 일은 없을 것 같다. 확실히 JWT 방식의 장점이 더 많고, Session 관리도 더 잘 될 것 같다.
벨로퍼트님 강의가 정말 많은 도움이 되고 있다....
반응형'개발 블로깅 > 기타 개념' 카테고리의 다른 글
[2019.06.25] AWS CloudWatch - AWS 서비스를 모니터링 해보자 (0) 2019.06.25 [2019.05.12] 컨테이너 방식 독립환경 - Docker 개념 (0) 2019.05.12 [2019.05.07] Sequelize - 조회,삽입,수정, 삭제 사용법 (0) 2019.05.07 [2019.05.06] 불필요한 github 업로드 방지 - gitignore 설정 (0) 2019.05.06 [2019.05.05] CORS...너는 대체 누구니..? (0) 2019.05.05