[Node.js]jsonwebtoken(JWT)토큰이란?

resilient

·

2021. 6. 21. 23:22

728x90
반응형

JWT 는 JSON Web Token의 약자로 전자 서명 된 URL-safe (URL로 이용할 수있는 문자 만 구성된)의 JSON이다.
전자 서명은 JSON 의 변조를 체크 할 수 있게되어 있다.
JWT는 속성 정보 (Claim)를 JSON 데이터 구조로 표현한 토큰으로 RFC7519 표준 이다.
JWT는 서버와 클라이언트 간 정보를 주고 받을 때 Http 리퀘스트 헤더에 JSON 토큰을 넣은 후 서버는 별도의 인증 과정없이 헤더에 포함되어 있는 JWT 정보를 통해 인증한다.
이때 사용되는 JSON 데이터는 URL-Safe 하도록 URL에 포함할 수 있는 문자만으로 만든다.

다음과 같은 상황에서 JWT 가 유용하게 사용 될 수 있다:

  • 회원 인증 : JWT 를 사용하는 가장 흔한 시나리오다. 유저가 로그인을 하면, 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달해준다. 그 후, 유저가 서버에 요청을 할 때 마다 JWT를 포함하여 전달한다. 서버가 클라이언트에게서 요청을 받을때 마다, 해당 토큰이 유효하고 인증됐는지 검증을 하고, 유저가 요청한 작업에 권한이 있는지 확인하여 작업을 처리한다.
    서버측에서는 유저의 세션을 유지 할 필요가 없다. 즉 유저가 로그인되어있는지 안되어있는지 신경 쓸 필요가 없고, 유저가 요청을 했을때 토큰만 확인하면 되니, 세션 관리가 필요 없어서 서버 자원을 많이 아낄 수 있죠.
  • 정보 교류 : JWT는 두 개체 사이에서 안정성있게 정보를 교환하기에 좋은 방법이다. 그 이유는, 정보가 sign 이 되어있기 때문에 정보를 보낸이가 바뀌진 않았는지, 또 정보가 도중에 조작되지는 않았는지 검증할 수 있다.

JWT의 생김새는 아래와 같다.

사진출처 : https://velopert.com/2389

 

JWT 프로세스는 아래와 같다.

사진 출처 : https://tansfil.tistory.com/58

동작 순서에 대해 설명하자면,

1 - 사용자 로그인

2 - 서버에서 1번에서 넘어온 데이터를 통해 DB의 사용자 정보와 일치하는지 확인

3 - 2번의 결과가 일치한다면 사용자의 고유 값(ID 등 )을 세션 저장소에 저장

4 - 3번에서 저장된 값과 연결되는 세션 ID를 발급

5 - 사용자에게 데이터와 Session Id를 포함해 응답, 사용자는 Session Id를 쿠키에 저장

6 - 앞으로의 요청은 5에서 저장한 쿠키를 포함해 요청.

7,8 - 6에서 같이 전송된 쿠키를 받아 세션 저장소에서 대조 한 뒤 정보를 가져옴

9 - 사용자에게 응답

 

나는 보통 JWT를 Node.js 에서 사용할 때 미들웨어로 만들어서 사용한다.

아래와 같이 jsonwebtoken을 설치해준다.

npm install jsonwebtoken
const jwt = require('jsonwebtoken');
// jsonwebtoken기반 로그인 방식 구현
const secret_config = require('./secret');
// 미들웨어 만들어줘서 사용
const jwtMiddleware = (req, res, next) => {
    //url로 부터 토큰을 읽어들인다.
    const token = req.headers['x-access-token'] || req.query.token;
    // token does not exist
    if(!token) {
        return res.status(403).json({
            isSuccess:false,
            code: 403,
            message: '로그인이 되어 있지 않습니다.'
        });
    }
    //비동기작업들을 순차적으로 진행해주는 promise를 생성하고 토큰을 해독하는 함수를 넣는다.
    const p = new Promise(
        (resolve, reject) => {
            jwt.verify(token, secret_config.jwtsecret , (err, verifiedToken) => {
                if(err) reject(err);
                resolve(verifiedToken)
            })
        }
    );

    // 토큰 유효성검사 실패시, 검증실패 res를 뿌린다.
    const onError = (error) => {
        res.status(403).json({
            isSuccess:false,
            code: 403,
            message:"검증 실패"
        });
    };

    // promise과정
    p.then((verifiedToken)=>{
        //비밀 번호 변경됐을 때 검증 부분 추가 할 곳
        req.verifiedToken = verifiedToken;
        next();
    }).catch(onError)
};

module.exports = jwtMiddleware;
반응형