1. JWT란?

  • JSON Web Token의 줄임말로 인증에 필요한 정보들을 암호화시킨 토큰을 뜻합니다.
  • JSON 객체를 사용해 정보를 안정성 있게 전달하는 웹표준입니다.
  • 사용자는 Access Token(JWT 토큰)을 HTTP 헤더에 실어 서버로 보내게 됩니다.
  • 예를 들어, 로그인 기능을 생각해보면 사용자가 로그인하면 서버에서 회원임을 인증하는 토큰을 넘겨줌으로써 이후 회원만 접근할 수 있는 서비스 영역에서 신분을 확인하는 데 쓰일 수 있습니다.

 

jwt.io 메인페이지

 

2. 사용법

토큰을 만들기 위해서는 크게 3가지, Header,Payload, Verify Signature가 필요합니다. 
Header : 위 3가지 정보를 암호화할 방식(alg), 타입(type) 등이 들어갑니다.
Payload : 서버에서 보낼 데이터가 들어갑니다. 일반적으로 유저의 고유 ID값, 유효기간이 들어갑니다.
  • Payload는 정보 하나하나를 각각 클레임 (claim)이라고 부른다.
  • Claim은 key/value 로 작성해야한다.
  • Claim도 registered claim, public claim, private claim으로 나눈다.
Verify Signature :  Base64 방식으로 인코딩한 Header,payload 그리고 SECRET KEY를 더한 후 서명됩니다.
            $.ajax({
                type: "POST",
                url: "/sign_in",
                data: {
                    role_give: role,
                    userid_give: userid,
                    password_give: password
                },
                success: function (response) {
                    if (response['result'] == 'success') {
                        $.cookie('mytoken', response['token'], {path: '/'});
                        {#window.location.replace("/")#}
                        window.location.href='/'
                    } else {
                        alert(response['msg'])
                    }
                }
            });
@application.route('/sign_in', methods=['POST'])
def sign_in():
    # 로그인
    role_receive = request.form['role_give']
    userid_receive = request.form['userid_give']
    password_receive = request.form['password_give']

    pw_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
    result = db.users.find_one({'role': role_receive, 'userid': userid_receive, 'password': pw_hash})

    if result is not None:
        payload = {
         'id': userid_receive,
         'exp': datetime.utcnow() + timedelta(seconds=60 * 60 * 24)  # 로그인 24시간 유지
        }

        token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')

        return jsonify({'result': 'success', 'token': token})
    # 찾지 못하면
    else:
        return jsonify({'result': 'fail', 'msg': '아이디/비밀번호가 일치하지 않습니다.'})
최종적인 결과 : Encoded Header + "." + Encoded Payload + "." + Verify Signature
Header, Payload는 인코딩될 뿐(16진수로 변경), 따로 암호화되지 않습니다. 따라서 JWT 토큰에서 Header, Payload는 누구나 디코딩하여 확인할 수 있습니다. 여기서 누구나 디코딩할 수 있다는 말은 Payload에는 유저의 중요한 정보(비밀번호)가 들어가면 쉽게 노출될 수 있다는 말이 됩니다. 

하지만 Verify Signature는 SECRET KEY를 알지 못하면 복호화할 수 없습니다. 

 

def getUserInfoByToken():

    token_kakao = request.cookies.get('kakao')
    token_receive = request.cookies.get('mytoken')
    user_info = ''

    if token_receive is not None:
        try:
            payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
            user_info = db.users.find_one({"userid": payload["id"]})
        except jwt.ExpiredSignatureError:
            return redirect(url_for("login", msg="로그인 시간이 만료되었습니다."))
        except jwt.exceptions.DecodeError:
            return redirect(url_for("login", msg="로그인 정보가 존재하지 않습니다."))

    if user_info is not None:
        return user_info;

    if user_info is None:
        user_info = 'a';
        return user_info;

 

3. 장&단점

 3-1) 장점

  • 세션/쿠키는 별도의 저장소의 관리가 필요합니다. 그러나 JWT는 발급한 후 검증만 하면 되기 때문에 추가 저장소가 필요 없습니다. 이는 Stateless 한 서버를 만드는 입장에서는 큰 강점입니다. 
  • Stateless는 어떠한 별도의 저장소도 사용하지 않는, 즉 상태를 저장하지 않는 것을 의미합니다. 이는 서버를 확장하거나 유지,보수하는데 유리합니다.
  • 토큰 기반으로 하는 다른 인증 시스템에 접근이 가능합니다.(높은 확장성)
  • 예를 들어 Facebook 로그인, Google 로그인 등은 모두 토큰을 기반으로 인증을 합니다. 이에 선택적으로 이름이나 이메일 등을 받을 수 있는 권한도 받을 수 있습니다. 
 

 3-2) 단점

  • 이미 발급된 JWT에 대해서는 돌이킬 수 없습니다. 세션/쿠키의 경우 만일 쿠키가 악의적으로 이용된다면, 해당하는 세션을 지워버리면 됩니다. 하지만 JWT는 한 번 발급되면 유효기간이 완료될 때 까지는 계속 사용이 가능합니다. 따라서 악의적인 사용자는 유효기간이 지나기 전까지 신나게 정보들을 털어갈 수 있습니다. 
  • SECRET KEY가 없으면 복호화가 안된다면서 왜 털려? 공격자가 매우 스마트하면 털리겠지  
    • 해결책 => 기존의 Access Token의 유효기간을 짧게 하고 Refresh Token이라는 새로운 토큰을 발급합니다. 그렇게 되면 Access Token을 탈취당해도 상대적으로 피해를 줄일 수 있습니다. 
 
  •  Payload 정보가 제한적입니다. 위에서 언급했다시피 Payload는 따로 암호화되지 않기 때문에 디코딩하면 누구나 정보를 확인할 수 있습니다. (세션/쿠키 방식에서는 유저의 정보가 전부 서버의 저장소에 안전하게 보관됩니다) 따라서 유저의 중요한 정보들은 Payload에 넣을 수 없습니다.
  • 세션/쿠키 방식에 비해 JWT의 길이는 깁니다. 따라서 인증이 필요한 요청이 많아질 수록 서버의 자원낭비가 발생하게 됩니다.

 

4. 세션/쿠키 인증방법

서버에서 받은 Session ID를 쿠키에 저장하여 사용

 

세션/쿠키 인증방법

 

2022.05.30 - [프로그래밍/개발지식] - 쿠키 & 세션

 

 

 

 

 

참조 블로그 : 그랩의 블로그

쉽게 알아보는 서버 인증 1편(세션/쿠키 , JWT) : https://tansfil.tistory.com/58?category=255594

'프로그래밍 > 개발지식' 카테고리의 다른 글

정처기 시험대비 메모장 2 - 22년 1회 필기  (0) 2022.05.04
정처기 시험대비 메모장 1  (0) 2022.05.03
해시함수란?  (0) 2022.05.03
API 키란?  (0) 2022.04.29
정적 웹페이지 vs. 동적 웹페이지  (0) 2022.04.29

+ Recent posts