JWT 란?

최더디·2020년 10월 20일
1

JWT 란?


  • JWT 란 "JSON Web Token" 의 약자이다.
  • JWT 는 웹표준(RFC 7519) 으로서 두 개체에서 JSON 객체를 사용하여 통신한다.
  • JWT 는 필요한 모든 정보를 자체적으로 지니고 있다.
    JWT 시스템에서 발급된 토큰은, 토큰에 대한 기본 정보, 전달 할 정보, 그리고 토큰이 검증됐다는 것을 증명해주는 signature 를 포함하고 있다.
  • JWT는 웹서버의 경우 HTTP의 헤더에 넣어서 전달할 수도 있고, URL의 파라미터로 전달할 수도 있다.

웹서버에서 JSON 을 통해 쉽게 인증을 하기 위해서 사용하는 거 같은데 ?

JWT 구성

  • Header : 3가지 요소를 암호화할 알고리즘 등과 같은 옵션이 들어간다.
  • Payload : 유저의 고유 ID 등 인증에 필요한 정보가 들어간다.
  • Signature : Header, Payload와 Secret Key가 더해져 암호화된다.

Header.PayLoad.Signature로 만들어진다.

Header와 Payload는 누구나 디코딩하여 내용을 확인할 수 있기 때문에 유저의 비밀번호 같은 정보는 넣지 않도록 한다. 하지만 Secret Key를 알지 못하면 VerifySignature는 복호화할 수 없다.

JWT의 흐름

  1. server가 token을 받아서 서명으로 유효한지 검증
  2. 유효하다고 판단하면 claim set을 decoding해서 token에 담긴 데이터를 열어봄
  3. 만료시간이 담겨있으므로 token이 사용가능한지 검사하고 이상이 없으면 바로 사용
  4. application에서 사용자 정보 확인하고 바로 정보 조회

"JWT란?" 에 관련된 글
https://velopert.com/2389
http://www.opennaru.com/opennaru-blog/jwt-json-web-token/
https://sanghaklee.tistory.com/47

Access Token


사용자가 로그인을 했을 때, 로그인을 어떻게 유지 시키는 방법은 다양한 방법으로 진화해왔다.
Cookie, Session 그 다음 단계를 거친 것이 바로 JWT를 이용한 토큰 방식의 사용자 인증 방식이다.
간략하게 설명하자면 토큰에 사용자 정보를 식별할 수 있는 정보를 담아 놓고, 인증이 필요할 때 이 JWT token을 사용하는 방식이다.

"Session-Cookie" vs "JWT(JSON Web Token)"


  • 확장성이 좋지 않다.
  • Stateful : 모든 사용자의 인증상태(Session)를 유지하고 있어야 한다.
  • Traffic 고려 : 사용자가 많아지면 Session 저장소가 Traffic을 감당해야 한다. (조회, 등록)
  • 공유 자원 : Server 증설 시 Session 저장소를 공유해야 한다.

JWT(JSON Web Token)

  • 확장성이 좋다.
  • Stateless : Session 저장소 처럼 사용자의 인증 상태 데이터를 별도 저장소로 유지할 필요가 없다.
  • Traffic 고려 X공유 자원 X : 각 Server가 토큰 발급만 잘 해주면 된다.

"Flask-JWT" vs "Flask-JWT-Extended"


Flask-JWT 보다 Flask-JWT-Extended 가 더 많은 기능을 가지고 있다.

또한 해당 pypi.org 사이트를 들어가 봤을 때, Release history 를 보면 Flask-JWT는 마지막 Release 가 2015/11월 이고, Flask-JWT-Extended는 2019/10월 이다.
이것만 봐도 어떤 것이 더 활성화 되는지 알 수 있다.

또한 https://pypi.org/project/Flask-JWT-Extended/ 해당 페이지의 Features 부분을 보면 "Flask-JWT-Extended는 View를 보호하기 위해 Flask에 JSON Web Token(JWT) 사용에 대한 지원을 추가 할 뿐만 아니라 JSON Web Token을 더 쉽게 사용할 수 있도록 내장 된 많은 유용한 (및 선택적 ) 기능도 추가합니다." 이렇게 적혀있다.

pip 설치


pip install Flask-JWT-Extended

예제


"""
__init__.py
"""

from flask import Flask, request, jsonify
from flask_jwt_extended import (
    JWTManager, jwt_required, create_access_token, get_jwt_identity
)

app = Flask(__name__)

# Setup the Flask-JWT-Extended extension
app.config['JWT_SECRET_KEY'] = 'super-secret'  # Change this!
jwt = JWTManager(app)

# Provide a method to create access tokens. The create_access_token()
# function is used to actually generate the token, and you can return
# it to the caller however you choose.
@app.route('/login', methods=['POST'])
def login():
    if not request.is_json:
        return jsonify({"msg": "Missing JSON in request"}), 400

    username = request.json.get('username')
    password = request.json.get('password')
    if not username:
        return jsonify({"msg": "Missing username parameter"}), 400
    if not password:
        return jsonify({"msg": "Missing password parameter"}), 400

    if username != 'test' or password != 'test':
        return jsonify({"msg": "Bad username or password"}), 401

    # Identity can be any data that is json serializable
    access_token = create_access_token(identity=username)
    return jsonify(access_token=access_token), 200

# Protect a view with jwt_required, which requires a valid access token
# in the request to access.
@app.route('/protected', methods=['GET'])
@jwt_required
def protected():
    # Access the identity of the current user with get_jwt_identity
    current_user = get_jwt_identity()
    return jsonify(logged_in_as=current_user), 200
  1. 우선 import 를 해준다
from flask_jwt_extended import (JWTManager, jwt_required, create_access_token, get_jwt_identity)
  1. SECRET-KEY 설정
app.config['JWT_SECRET_KEY'] = 'super-secret'

위의 문장은 config.py 로 옮겨서 적을 수도 있다.
(아래와 같이 secret-key는 분리해서 적은 뒤 gitignore 하는게 좋다.)

# config.py
import os
class Config(object):
    JWT_SECRET_KEY = 'super-secert'
  1. JWTManager 를 통해 app 과 연결 (2가지 방법)
    JWTManager는 flask instance에서 JWT을 사용할 수 있게 만들어주는 역할을 한다.
    JWTManager(app)을 설정해줘야 flask istance에서 jwt를 사용할 수 있게 된다.
#1
jwt = JWTManager(app)    # flask instance에서 jwt을 초기화(initialize) 하는 것

#2
jwt = JWTManager()
jwt.init_app(app) 

자주 사용할 것 같은 코드


  1. create_access_token(identity="값")
  2. @jwt_required
  3. get_jwt_identity()

create_access_token(identity="값")

token 을 만들어주는 코드이다.

값 부분에는 주로 username, user_id 가 들어가는 것 같다.

@jwt_required

end-point 호출을 허용하기 전에 요청자가 유효한 access token을 가지고 있는지 확인한다.

get_jwt_identity()

end-point에 액세스하는 JWT의 ID를 반환한다(JWT가 없으면 대신 'None'이 반환된다).

# token 생성
access_token = create_access_token(identity="admin")

# print(current_user) => "admin" 값이 나온다.
current_user = get_jwt_identity()

메소드, 매개변수 등은 아래 링크를 통해 더 많이 볼 수 있다.
https://flask-jwt-extended.readthedocs.io/en/stable/api/

질문


  • 내가 access_token = create_access_token() 을 통해서 token 을 만들었다고 치자.
    return jsonify("access_token": access_token) 를 통해 return 해주게 될 것이다.
    그러면 백앤드에서 해야할 일은 끝난 것인가 ?
    즉, 내가 Token 을 만들어서 넘겨주면, 프론트앤드에서 return 받은 token 을 사용해 다른 url 로 넘어갈 때 값을 넘겨주는 것인가 ?
profile
focus on why

0개의 댓글