RestFul API

JWT ์•”ํ˜ธํ™”(์ธ์ฆํ† ํฐ) ์‚ฌ์šฉํ•˜์—ฌ ํšŒ์›๊ฐ€์ž… API์— ์ ์šฉํ•˜๊ธฐ

567Rabbit 2024. 5. 22. 13:03

https://codebunny99.tistory.com/93

 

MySQL DB์™€ Postman์„ ์—ฐ๋™ํ•˜์—ฌ ํšŒ์›๊ฐ€์ž… API ๋งŒ๋“ค๊ธฐ

์ด๋ฉ”์ผ ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ pip install email-validatorpip install passlibpip install psycopg2-binary   DB์™€ postman์„ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜ ๊ธ€์„ ์ฐธ๊ณ ํ•œ๋‹ค  https://codebunny

codebunny99.tistory.com

์œ„ ๋ธ”๋กœ๊ทธ ๊ธ€์„ ๋จผ์ € ๋ณด๊ณ  ์˜จ๋‹ค.

 

 

 

 

***** ์ค‘์š” ******

>  user_id๊ฐ€ ๋…ธ์ถœ๋˜๋ฉด ์•ˆ๋˜๋ฏ€๋กœ user_id๋ฅผ ์•”ํ˜ธํ™”ํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

 

 

 

 

JWT(JSON WEP TOKEN) ์•”ํ˜ธํ™”

 

JWT๋Š” ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ,

JWT_ACCESS_TOKEN_EXPIRES ์„ค์ •์„ ์‚ฌ์šฉํ•˜์—ฌ ํ† ํฐ์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

JWT๋Š” ์ž์ฒด์ ์œผ๋กœ Header, Body, Signature๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

 

Header : ํ† ํฐ์˜ ํƒ€์ž…, ์„œ๋ช… ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ •๋ณด

Body : ํด๋ ˆ์ž„ ์ •๋ณด

Signature : ํ† ํฐ์˜ ๋ฌด๊ฒฐ์„ฑ ๋ณด์žฅ

 

 

Postman์—์„œ API ์š”์ฒญ ์‹œ ํ—ค๋”(Header)์— ์ธ์ฆํ† ํฐ์„ ๋‘๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

=> Body์—์„œ user_id๊ฐ€ ๋…ธ์ถœ๋˜์–ด๋„, Header์—์„œ ์ธ์ฆํ† ํฐ์„ ๊ฑฐ์ณ์•ผ ํ•˜๋ฏ€๋กœ ๋”์šฑ ์•ˆ์ „ํ•˜๋‹ค

 

 

 

 

 

Flask-JWT-Extended ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

 

pip install flask-jwt-extended

 

 

 

 

config ํŒŒ์ผ์— JWT ์•”ํ˜ธํ™”๋ฅผ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค

 

#JWT ๊ด€๋ จ ๋ณ€์ˆ˜ ์…‹ํŒ…
    JWT_SECRET_KEY = 'djaiwnb, 12850sksj' # ์ž์œ ๋กญ๊ฒŒ ์„ค์ • ๋…ธ์ถœ๋˜๋ฉด ์•ˆ๋จ
    JWT_ACCESS_TOKEN_EXPIRES = False
    PROPAGATE_EXCEPTIONS = True # JWT์—์„œ ๋ฌธ์ œ ๋ฐœ์ƒํ•˜๋ฉด ์•Œ๋ ค๋‹ฌ๋ผ๋Š” ์ฝ”๋“œ

 

 

 

 

app.py ํŒŒ์ผ์— ์ถ”๊ฐ€

 

from flask_jwt_extended import JWTManager
from config import Config

# app = Flask(__name__) ์•„๋ž˜์— ์ถ”๊ฐ€

# ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์…‹ํŒ…
app.config.from_object(Config)

# JWT ๋งค๋‹ˆ์ € ์ดˆ๊ธฐํ™”
jwt = JWTManager(app)

# api = Api(app) ์œ„์— ์ถ”๊ฐ€

 

 

 

 

 

user.py์— ์ถ”๊ฐ€, ๋ณ€๊ฒฝ

 

from email_validator import EmailNotValidError, validate_email
from flask import request
from flask_jwt_extended import create_access_token
from mysql.connector import Error
from flask_restful import Resource
from mysql_connection import get_connection
from utils import check_password, hash_password


class UserRegisterResource(Resource) :
    
    def post(self):
        
        # 1. ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ณด๋‚ธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์ค€๋‹ค.
        data = request.get_json()
        print(data)
        
        # 2. ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ์žˆ๋Š”์ง€ ํ™•์ธ
        if data.get('email') is None or data.get('email').strip() == '' or \
            data.get('username') is None or data.get('username').strip() == '' or \
            data.get('password') is None or data.get('password').strip() == '':
            return {'result' : 'fail'},400

        # 3. ์ด๋ฉ”์ผ์ฃผ์†Œ ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธํ•œ๋‹ค.
        try :
            validate_email(data['email'])
        except EmailNotValidError as e :
            return {'result' : 'fail', 'error' : str(e)},400

        # 4. ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธธ์ด๊ฐ€ ์œ ํšจํ•œ์ง€ ์ฒดํฌํ•œ๋‹ค.
        #    ์˜ˆ) ๋น„๋ฒˆ์€ 4์ž๋ฆฌ ์ด์ƒ 12์ž๋ฆฌ ์ดํ•˜!
        if len(data['password']) < 4 or len(data['password']) > 12:
            return {'result' : 'fail'}, 400

        # 5. ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•”ํ˜ธํ™” ํ•œ๋‹ค. 
        password = hash_password( data['password'] )
        print(password)

        # 6. DB์— ์ €์žฅํ•œ๋‹ค.
        try:
            connection = get_connection()
            query = '''insert into user
                    (username, email, password)
                    values
                    (%s, %s, %s );'''
            record = (data['username'], data['email'], password)
            cursor = connection.cursor()
            cursor.execute(query, record)
            connection.commit()

            ### DB์— ํšŒ์›๊ฐ€์ž…ํ•˜์—ฌ, user ํ…Œ์ด๋ธ”์— insert๋œ ํ›„,
            ### ์ด user ํ…Œ์ด๋ธ”์˜ id๊ฐ’์„ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค.
            user_id = cursor.lastrowid

            cursor.close()
            connection.close()

        except Error as e:
            if cursor is not None:
                cursor.close()
            if connection is not None:
                connection.close()
            return {'result':'fail', 'error':str(e)}, 500    
        
        
        ### 6-2. user_id๋ฅผ ๋ฐ”๋กœ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ณด๋‚ด๋ฉด ์•ˆ๋˜๊ณ  JWT๋กœ ์•”ํ˜ธํ™”ํ•ด์„œ ์ธ์ฆํ† ํฐ์„ ๋ณด๋‚ด์•ผ ํ•œ๋‹ค.
        access_token = create_access_token(user_id)
        

        # 7. ์‘๋‹ตํ•  ๋ฐ์ดํ„ฐ๋ฅผ JSON์œผ๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฆฌํ„ด.        
        return { 'result' : 'success' , 'user_id' : user_id , 'access_token' : access_token } , 200 # 200์€ ๋””ํดํŠธ๊ฐ’์ด๋ฏ€๋กœ ์•ˆ์จ๋„ ๋จ

 

 

 

 

 

 

ํŒŒ์ผ์„ ์ €์žฅํ•˜๊ณ , vscode ํ„ฐ๋ฏธ๋„ cmd์— flask run ํ•œ๋‹ค 

 

send๋ฅผ ๋ˆŒ๋Ÿฌ๋ณด๋ฉด ์ธ์ฆํ† ํฐ์ด ์•”ํ˜ธํ™”๋˜์—ˆ๋‹ค.