2.22

홍왕열·2022년 2월 22일
0

TIL

목록 보기
20/56

jwt.sign --> 토큰 생성

const jwt = require('jsonwebtoken');

let userInfo = {id: 1, username: 'inyong'};
let secretKey = 'SeCrEtKeYfOrHaShInG';
let 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번째 인자의 콜백함수로 받을 수 있으므로 넣어준 함수.

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
  })
});

let server = app.listen(3000, function(){
  console.log("Express server has started on port 3000");
});

jwt.sign()함수는 비동기 함수이므로 Promise 처리를 해줘야 한다. 하단 부분에 res.send()로 사용자에게 토큰을 보내준다.

jwt.verify --> 토큰 인증(확인)

사용자는 서버에게서 토큰을 받은 후, 서버에게 요청을 보낼 때, 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

let 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 관리도 더 잘 될 것 같다.

공부용으로 퍼옴 : https://helloinyong.tistory.com/111

findOne 공부하기

profile
코딩 일기장

0개의 댓글