개발/백엔드

server - login을 위한 token 설정 및 logout 을 위한 token 방지

웅'jk 2023. 1. 5. 16:11

이전 포스팅에서 회원가입을 진행을 하였습니다.

 

이제 login/logout을 작성하고 내가 발급받은 토큰으로 내 데이터만 수정 / 삭제 가능하도록 작성해봅시다.

 

먼저 로그인 입니다.

 # 클라이언트 가 보내줄데이터
{
 "email":"abc12345@naver.com",
 "password":"12345"
 }
 def post(self) :
        data = request.get_json()

        # DB 로부터 해당 유저의 데이터를 가져온다.
        try :
            connection = get_connection()
            query = '''select * from user where email = %s;'''
            record = (data['email'],)
            cursor = connection.cursor(dictionary=True)
            cursor.execute(query,record)
            result_list = cursor.fetchall()
            if len(result_list) == 0 :
                return {'result':'fail','error':'회원이 아닙니다.'},400
            # json 처리를 위한 변경
            i = 0
            for row in result_list : 
               result_list[i]['created_at'] = row['created_at'].isoformat()
               result_list[i]['updated_at'] = row['updated_at'].isoformat()
               i = i + 1
            cursor.close()
            connection.close()
        except Error as e :
            cursor.close()
            connection.close()
            return {'error' : str(e)},500
        print(result_list)
        # DB에서 가져온 데이터와 입력한 비밀번호가 맞는지 확인하기.
        check = check_password(data['password'] , result_list[0]['password'])
        if  check == False :
            return {'error': '비밀번호가 틀렸습니다.'},400
        # 클라이언트에게 id값 jwt 토큰으로 보내주기
        access_token = create_access_token( result_list[0]['id'] )

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

이러면 이제 사용자는 토큰을 받아오게 되며 이 토큰을 이용해야서 내 정보만을 수정할 수 있도록

기존 api를 수정합니다.

 

저는 내 리스트를 가져오기 위한 API 1가지만 예로 작성하겠습니다.

from flask_jwt_extended import jwt_required,get_jwt_identity
class RecipeResourceMe(Resource) : 
    @jwt_required()
    def get(self) :
        user_id = get_jwt_identity()
        try :
            connection = get_connection()
            query = '''select * from recipe where user_id = %s ;'''
            record = (user_id , )
            cursor = connection.cursor(dictionary=True)
            cursor.execute(query,record)
            result_list = cursor.fetchall()
            i = 0
            for row in result_list : 
                result_list[i]['created_at'] = row['created_at'].isoformat()
                result_list[i]['updated_at'] = row['updated_at'].isoformat()
                i = i + 1
            
            cursor.close()
            connection.close()

        except Error as e :
            cursor.close()
            connection.close()
            return {'result':'fail','error':str(e)},400
        return {'result':'success', 'items' : result_list }, 200

먼저 토큰이 있어야지 작동할 수 있게 @jwt_required()를 표시합니다.

그리고 이 받아온 토큰의 원래 값을 저장하기 위해서 get_jwt_identity() 함수를 이용하여 저장합니다.

그리고 받아온 회원의 id 로 조회를 하도록 소스를 작성합니다.

 

* 여기서 그전 포스팅에서 작성한 recipe는 user_id 가 없기때문에 추가를 해줬습니다.

 

로그아웃을 해봅시다.

서버에서 로그아웃을 처리하는 방법은 내가 발급한 토큰들을 저장하여 이 토큰은 사용이 안된다고 명시해주면 됩니다.

이 부분은 jwt 라이브러리 명세서에 적혀있기 때문에 참고하였습니다.


# user.py
# 로그아웃된 토큰을 저장할 set 만든다.
jwt_blacklist = set()
class UserLogoutResource(Resource) :
    @jwt_required()
    def post(self) :
        
        jti = get_jwt()['jti']
        jwt_blacklist.add(jti)
        return {'result':'success Logout'} , 200

이제 app.py 에서 이 토큰들을 사용하지말라고 작성합니다.

# app.py
from resources.user import jwt_blacklist
# 아까 작성한 blacklist 가 있는 소스파일에서 가져옵니다.


@jwt.token_in_blocklist_loader
def check_if_token_is_revoke(jwt_header,jwt_payload) :
    jti = jwt_payload['jti']
    return jti in jwt_blacklist