본문 바로가기
백엔드/API

[API] 인증토큰 JWT, 로그인과 로그아웃: JWTManager, create_access_token, token_in_blocklist_loader

by eyoo 2022. 6. 20.

회원가입하거나 로그인 할때, 유저 정보를 양방향 암호화해서 처리하는 JWT를 사용한다. 

 

관련 웹사이트:

https://flask-jwt-extended.readthedocs.io/en/stable/

 

Flask-JWT-Extended’s Documentation — flask-jwt-extended 4.4.1 documentation

 

flask-jwt-extended.readthedocs.io

 

먼저 JWT 라이브러리를 다운로드 한다.

 

pip install flask-jwt-extended

 

config.py 파일을 생성하여 Config코드를 작성한다.

 

class Config:
    JWT_SECRET_KEY = 'yhacademy1029##hello'  # 절대 노출시키면 안되는 키
    JWT_ACCESS_TOKEN_EXPIRES = False # True로 설정하면 3분의 유효기간이 생긴다.
    PROPAGATE_EXCEPTIONS = True # JWT가 예외처리를 해주는 옵션

 

 

본 파일에 코드를 추가한다.

 

from config import Config
from flask_jwt_extended import create_access_token, get_jwt, jwt_required

app = Flask(__name__) # 이 밑에서 추가

# 환경변수 세팅
app.config.from_object(Config)

# JWT 토큰 라이브러리 만들기
jwt = JWTManager(app)

 

 

이제 회원가입할때 유저 아이디를 JWT의 create_access_token를 통해 암호화 할수있다.

 

            # DB에 저장된 ID값 가져오기
            user_id = cursor.lastrowid

            # 6. 자원 해제
            cursor.close()

...

        # user_id를 바로 보내면 안되고 JWT로 암호화한뒤 보낸다.
        access_token = create_access_token(user_id)

        return {"result":"success" , "access_token" : access_token}, 200

 

 

로그인 할때도 유저 아이디를 create_access_token를 통해 암호화 할수있다.

 

        # result_list의 행의갯수가 1개면 유저데이터를 받아온것이고 0 이면 등록되지 않은 회원
        if len(result_list) != 1:
            return {'error':'해당되는 이메일 정보가 없습니다.'}, 400

        # 비밀번호가 맞는지 확인
        user_info = result_list[0]
        check = check_password(data['password'],user_info['password'])
        if check == False:
            return {'error':'비밀번호가 맞지 않습니다.'}, 400

        access_token = create_access_token(user_info['id'])
        
        return {'result' : 'success' ,'access_token':access_token} ,200

 

 

또한 유저가 게시물을 작성할때도 포스트맨에서 Header에 Key와 Value를 설정하여 유저 아이디를 암호화 할수있다.

 

# Key에는 Authorization을 입력한다.

# Value에는 Bearer를 입력하고 한칸 뛰어서 access_token을 입력한다.

 

 

그 후 코드에서 get_jwt_identity로 복호화하여 변수로 만들고 이를 excute한다.

 

from flask_jwt_extended import get_jwt_identity, jwt_required

	@jwt_required() # def 메서드 위에 작성
    def post(self):
        # api 실행코드를 작성

        # 클라이언트에서 body부분에 작성한 json을 받아오는 코드
        data = request.get_json()

        # 유저 아이디 복호화
        user_id = get_jwt_identity()  
        
...
    
        # 2. 쿼리문 만들기
        query = '''insert into recipe
                (name, description, cook_time, directions, user_id)
                values
                (%s, %s, %s, %s, %s);'''

        record = (data['name'], data['description'], data['cook_time'], data['directions'], user_id  )

 

 

JWT_ACCESS_TOKEN_EXPIRES를 True로 설정하여 토큰의 유효기간을 정할수있다.

access_token = create_access_token(user_info['id'],expires_delta=datetime.timedelta(minutes=1))

# 학습을 위해 1분으로 설정했지만 원할한 사용환경을 위해 조금 더 길게 만들어 두자..

 

 

로그아웃할때는 로그아웃 기능을 할 클래스 위에 set을 jwt_blacklist 변수로 저장하고, 클래스 아래에 jwt_required를 사용하여 jwt 딕셔너리에서 jti 데이터(JWT ID, 토큰 식별자)를 가져와 set에 저장해야 한다.

 

jwt_blacklist = set()
# 로그아웃하는 기능의 클래스
class UserLogoutResource(Resource):

    @jwt_required()
    def post(self):

        jti = get_jwt()['jti']

        jwt_blacklist.add(jti)
        return {'result':'success'}, 200

# 클라이언트의 헤더가 set에서 블랙리스트에 있는 토큰인지 확인한 뒤 해당 기능을 실행할지 말지 결정할수있다.

 

 

본 파일인 app.py 파일에 token_in_blocklist_loader와 check_if_token_is_revoke 함수를 사용하여 로그아웃 기능을 사용할수 있도록 설정해야한다.

 

from resources.user import jwt_blacklist

# JWT 토큰 라이브러리 만들기
jwt = JWTManager(app)

# 로그아웃된 토큰이 들어있는 set을 jwt에 알려준다
@jwt.token_in_blocklist_loader
def check_if_token_is_revoke(jwt_header, jwt_payload):
    jti = jwt_payload['jti']
    return jti in jwt_blacklist

# JWTManager 코드 바로 밑에 작성한다.

# 앞서 작성했던 jwt_blacklist 세트를 임포트한다.

# check_if_token_is_revoke 함수는 임의로 설정한것이 아닌 메뉴얼에 나온 그대로를 사용한다.

 

 

 

 

 

댓글