ruriruriya

[RESTful API] Python Flask - JWT 회원가입/로그인 API 토큰 생성 및 처리 방법 본문

Python Flask

[RESTful API] Python Flask - JWT 회원가입/로그인 API 토큰 생성 및 처리 방법

루리야ㅑ 2023. 12. 12. 21:04
반응형

JWT란 JSON Web Token의 약자로, JSON포맷으로 구성된 경량의 토큰으로, 정보를 안전하게 전달하기 위해 사용된다.

JWT는 클라이언트와 서버 간의 정보를 주고받을 때 사용자의 인증과 관련된 정보를 토큰으로 안전하게 전송하고 그 토큰으로 로그인 상태를 유지하는 등에 쓰인다. 

 

JWT의 장점

토큰 자체에 정보를 담고 있어서 서버에 따로 상태를 유지할 필요가 없다.
토큰을 사용하여 토큰이 변조되지 않았음을 쉽게 확인할 수 있다.

 

회원가입 API에서 JWT 토큰 발급

1. 사용자 정보 입력

사용자가 회원가입 양식을 작성하고 필요한 정보를 입력

from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error

from email_validator import validate_email, EmailNotValidError

from utils import check_password, hash_password
        # 이메일주소 확인하는 라이브러리 설치

#필수 import 문

class UserRegisterResource(Resource) :

    def post(self) :

        # 1. 클라이언트가 보낸 데이터를 받는다.
        data = request.get_json()


2. 사용자 정보 유효성 검사

입력된 정보가 양식에 틀리지 않는 지, 중복되지 않았는지 확인.

from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error

from email_validator import validate_email, EmailNotValidError

from utils import check_password, hash_password
        # 이메일주소 확인하는 라이브러리 설치

#필수 import 문

class UserRegisterResource(Resource) :

    def post(self) :

        # 1. 클라이언트가 보낸 데이터를 받는다.
        data = request.get_json()
        
        # 2. 이메일 주소 형식이 올바른지 확인한다.
        try :
            validate_email(data['email'])
        except EmailNotValidError as e : 
            print(e)
            return {'error':str(e)}, 400
        
        # 3. 비밀번호 길이가 유효한지 체크한다.
        # 만약, 비번은 4자리 이상 14자리 이하라고 한다면
        # 이런 것을 여기서 체크한다.
        
        if len(data['password']) < 4 or len(data['password']) > 14 :
            return {'error':'비번길이가 올바르지 않습니다.'}, 400


3. 사용자 정보 저장

유효한 정보인 경우, 사용자 정보를 데이터베이스에 저장한다.
이때, 비밀번호는 해싱(hashing)으로 암호화 한 뒤 다시 저장한다.

from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error

from email_validator import validate_email, EmailNotValidError

from utils import check_password, hash_password
        # 이메일주소 확인하는 라이브러리 설치

#필수 import 문

class UserRegisterResource(Resource) :

    def post(self) :

        # 1. 클라이언트가 보낸 데이터를 받는다.
        data = request.get_json()
        
        # 2. 이메일 주소 형식이 올바른지 확인한다.
        try :
            validate_email(data['email'])
        except EmailNotValidError as e : 
            print(e)
            return {'error':str(e)}, 400
        
        # 3. 비밀번호 길이가 유효한지 체크한다.
        # 만약, 비번은 4자리 이상 14자리 이하라고 한다면
        # 이런 것을 여기서 체크한다.
        
        if len(data['password']) < 4 or len(data['password']) > 14 :
            return {'error':'비번길이가 올바르지 않습니다.'}, 400
        
        # 4. 비밀번호를 암호화 한다.
        password = hash_password(data['password'])
        
        print(password)

        # 5. DB의 user 테이블에 저장
        try : 
            connection = get_connection()
            query = '''insert into user
                        (username, email, password)
                        values
                        (%s,%s,%s);'''
            record = (data['username'],
                      data['email'],
                    password) # 암호화된 비밀번호의 변수를 넣어야함 딕셔너리 X
            
            cursor = connection.cursor()
            cursor.execute(query, record)
            connection.commit()

            #### 테이블에 방금 insert한 데이터의
            #### 아이디를 가져오는 방법

            user_id = cursor.lastrowid

            cursor.close()
            connection.close()
        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return{'error':str(e)}, 500

        # ★6. user 테이블의 id로
        #      JWT 토큰을 만들어야 한다.
        
        # user_id 파라미터 암호화(양방향 암호화)
        access_token = create_access_token(user_id)

        # 7. 생성된 토큰을  클라이언트을 응답. response
        return {'result':'success','access_token':access_token}, 200

 

4. 포스트맨에서 request

포스트맨에서 관련 정보를 입력하면
암호화된 비밀번호와 필요한 정보가 user 테이블에 추가되는 것을 확인할 수 있다.

 

로그인 API에서 토큰 생성

1. 사용자 인증

사용자가 제공한 로그인 정보를 기반으로 사용자를 인증 (예: 아이디와 비밀번호 확인)

from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error

from email_validator import validate_email, EmailNotValidError
from utils import check_password, hash_password

class UserLoginResource(Resource):

    def post(self) : 

        # 1. 클라이언트로부터 데이터를 받아온다.
        data = request.get_json()

        # 2. 유저 테이블에, 이 이메일주소로
        #    데이터를 가져온다.
        try :
            connection = get_connection()
            query = '''select *
                        from user
                        where email = %s;'''
            record = (data['email'],)

            cursor = connection.cursor(dictionary=True) #sql select 할 땐 꼭 dictionary=True
            cursor.execute(query,record)

            result_list = cursor.fetchall()

            print(result_list)

            cursor.close()
            connection.close()

        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {'error':str(e)}, 500

        # 회원가입을 안한 경우, 리스트에 없다면
        if len(result_list) == 0 :
            return{"error":"회원가입을 하세요."}, 400

        # 회원일 경우, 비밀번호가 맞는 지 체크
        #(지금 유저가 입력한 비밀번호, DB에 저장되어 있는 비밀번호)

        check = check_password(data['password'], result_list[0]['password']) 

        # 비번이 맞지 않는 경우
        if check == False :
            return {'error' :'비번이 맞지 않습니다.'}, 406 # not access

 

2. JWT 생성

인증이 성공하면, 서버는 고유한 JWT를 생성한다.

from flask import request
from flask_jwt_extended import create_access_token
from flask_restful import Resource
from mysql_connection import get_connection
from mysql.connector import Error

from email_validator import validate_email, EmailNotValidError
from utils import check_password, hash_password

class UserLoginResource(Resource):

    def post(self) : 

        # 1. 클라이언트로부터 데이터를 받아온다.
        data = request.get_json()

        # 2. 유저 테이블에, 이 이메일주소로
        #    데이터를 가져온다.
        try :
            connection = get_connection()
            query = '''select *
                        from user
                        where email = %s;'''
            record = (data['email'],)

            cursor = connection.cursor(dictionary=True) #sql select 할 땐 꼭 dictionary=True
            cursor.execute(query,record)

            result_list = cursor.fetchall()

            print(result_list)

            cursor.close()
            connection.close()



        except Error as e :
            print(e)
            cursor.close()
            connection.close()
            return {'error':str(e)}, 500

        # 회원가입을 안한 경우, 리스트에 없다면
        if len(result_list) == 0 :
            return{"error":"회원가입을 하세요."}, 400

        # 회원일 경우, 비밀번호가 맞는 지 체크
        #(지금 유저가 입력한 비밀번호, DB에 저장되어 있는 비밀번호)

        check = check_password(data['password'], result_list[0]['password']) 

        # 비번이 맞지 않는 경우
        if check == False :
            return {'error' :'비번이 맞지 않습니다.'}, 406 # not access
        
        # JWT 토큰을 만들어서, 클라이언트에게 응답
        access_token = create_access_token(result_list[0]['id'])
                
        return {'result':'success','access_token':access_token}, 200

 

3. JWT 발급

서버는 JWT를 클라이언트에게 응답으로 보내거나,
특정 데이터 형태로 클라이언트에 전달한다.

본인은 포스트맨에서 로그인을 해보았다.
로그인을 하니 아래 토큰이 발급되었다.

클라이언트는 이 토큰을 헤더 등에 넣어서 서비스를 이용할 수 있다.

포스트맨에서 로그인시 토큰 생성 응답

JWT 토큰 활용법

클라이언트는 로그인 후 서버에 요청할 때
JWT를 Header에 Authorization 등의 방식으로 전달한다.

이렇게 회원만의 서비스를 이용할 수 있다.

포스트맨 API Headers

 

반응형