본문 바로가기
BIG DATA/PYTHON

[PYTHON] Flask에서 JWT(JSON Web Token)를 활용한 로그인 유지하기

by 라일리T 2025. 3. 7.

Flask에서 JWT(JSON Web Token)를 활용한 로그인 유지하기

이전 글에서는 이메일 인증 시스템을 구축하여, 사용자가 이메일을 통해 계정을 활성화하도록 만들었습니다.
이번 글에서는 JWT(JSON Web Token)를 이용하여 로그인 상태를 유지하는 방법을 배워보겠습니다.

 

JWT란?
Flask에서 JWT를 활용한 로그인 구현
토큰을 이용한 인증 시스템 구축

 

 

[PYTHON] Flask에서 이메일 인증 구현하기

Flask에서 이메일 인증 구현하기이전 글에서는 Flask에서 파일 업로드 기능을 이용해 프로필 사진을 추가하는 방법을 배웠습니다.이번 글에서는 회원가입 시 이메일 인증 기능을 구현하는 방법을

englishforkid.tistory.com

 


1. JWT란?

JWT(JSON Web Token)는 로그인 상태를 유지하기 위한 토큰 기반 인증 방식입니다.

🔹 JWT 구조
JWT는 3가지 부분으로 구성됩니다.

헤더(Header).페이로드(Payload).서명(Signature)

각 부분은 .으로 구분되며, Base64로 인코딩됩니다.

헤더 (Header) → 사용된 암호화 알고리즘 정보 포함
페이로드 (Payload) → 사용자 정보 (ID, 이메일 등) 포함
서명 (Signature) → 토큰 변조 방지를 위한 해싱값


2. Flask에서 JWT 사용을 위한 환경 설정

📌 PyJWT 라이브러리 설치

pip install PyJWT flask

📌 JWT 관련 설정 (config.py)

import os

SECRET_KEY = os.urandom(24)  # JWT 서명을 위한 비밀키
JWT_ALGORITHM = "HS256"  # 해싱 알고리즘 설정
JWT_EXPIRATION = 3600  # 토큰 만료 시간 (1시간)

✅ SECRET_KEY → JWT 서명을 위한 비밀 키
✅ HS256 → 보편적으로 사용되는 HMAC SHA-256 해싱 알고리즘
✅ JWT_EXPIRATION = 3600 → 토큰 만료 시간을 1시간으로 설정


3. JWT 토큰 생성 및 검증 함수

📌 JWT 생성 및 검증 (utils.py)

import jwt
import datetime
from flask import current_app

def generate_jwt(user_id):
    """사용자의 JWT 토큰을 생성"""
    payload = {
        "user_id": user_id,
        "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=current_app.config["JWT_EXPIRATION"])
    }
    token = jwt.encode(payload, current_app.config["SECRET_KEY"], algorithm=current_app.config["JWT_ALGORITHM"])
    return token

def verify_jwt(token):
    """JWT 토큰을 검증하고 사용자 ID 반환"""
    try:
        payload = jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=[current_app.config["JWT_ALGORITHM"]])
        return payload["user_id"]
    except jwt.ExpiredSignatureError:
        return None  # 토큰 만료
    except jwt.InvalidTokenError:
        return None  # 잘못된 토큰

✅ generate_jwt(user_id) → 로그인 시 JWT를 생성
✅ verify_jwt(token) → 토큰 검증 후 사용자 ID 반환


4. 로그인 시 JWT 발급

📌 로그인 시 JWT 생성 (app.py)

from flask import Flask, request, jsonify
import sqlite3

app = Flask(__name__)
app.config.from_pyfile("config.py")

@app.route("/login", methods=["POST"])
def login():
    data = request.json
    email = data.get("email")
    password = data.get("password")

    conn = sqlite3.connect("users.db")
    cursor = conn.cursor()
    cursor.execute("SELECT id, verified FROM users WHERE email = ? AND password = ?", (email, password))
    user = cursor.fetchone()
    conn.close()

    if user:
        user_id, verified = user
        if not verified:
            return jsonify({"error": "이메일 인증이 필요합니다."}), 400
        
        token = generate_jwt(user_id)
        return jsonify({"token": token})
    
    return jsonify({"error": "이메일 또는 비밀번호가 잘못되었습니다."}), 401

✅ request.json → JSON 데이터에서 이메일과 비밀번호 추출
✅ generate_jwt(user_id) → 로그인 성공 시 JWT 생성 후 반환
클라이언트는 이 토큰을 저장 후 요청 시 함께 전송


5. JWT를 이용한 인증된 요청 처리

📌 JWT를 이용한 인증 라우트 (app.py)

from flask import request

def login_required(func):
    """JWT 인증이 필요한 라우트를 위한 데코레이터"""
    def wrapper(*args, **kwargs):
        token = request.headers.get("Authorization")
        if not token:
            return jsonify({"error": "토큰이 필요합니다."}), 401
        
        user_id = verify_jwt(token)
        if not user_id:
            return jsonify({"error": "유효하지 않은 토큰입니다."}), 401
        
        return func(user_id, *args, **kwargs)
    return wrapper

@app.route("/profile", methods=["GET"])
@login_required
def profile(user_id):
    """인증된 사용자의 프로필 정보 반환"""
    conn = sqlite3.connect("users.db")
    cursor = conn.cursor()
    cursor.execute("SELECT username, email FROM users WHERE id = ?", (user_id,))
    user = cursor.fetchone()
    conn.close()

    if user:
        username, email = user
        return jsonify({"username": username, "email": email})
    
    return jsonify({"error": "사용자를 찾을 수 없습니다."}), 404

✅ Authorization 헤더에서 JWT 토큰 추출
✅ verify_jwt(token) → 유효한 토큰인지 검증
✅ @login_required 데코레이터를 사용하여 인증된 요청만 허용


6. 클라이언트에서 JWT 사용 방법

로그인 성공 시 클라이언트는 JWT를 저장하고, 이후 요청을 보낼 때 헤더에 추가합니다.

📌 로그인 요청 (POST /login)

{
    "email": "user@example.com",
    "password": "mypassword"
}

📌 서버 응답 (JWT 반환)

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}

📌 인증된 요청 보내기 (GET /profile)

GET /profile HTTP/1.1
Authorization: eyJhbGciOiJIUzI1NiIsInR5c...

📌 서버 응답 (프로필 정보 반환)

{
    "username": "user123",
    "email": "user@example.com"
}

7. JWT 토큰 만료 시 처리

JWT는 만료 시간이 있습니다.
만료된 토큰을 사용하면 다음과 같은 응답을 받습니다.

📌 만료된 토큰 사용 시 응답

{
    "error": "유효하지 않은 토큰입니다."
}

이 경우, 사용자는 다시 로그인하여 새로운 토큰을 받아야 합니다.


8. 결론

이번 글에서는 Flask에서 JWT를 활용한 로그인 유지 방법을 배웠습니다.

JWT를 이용해 로그인 후 토큰 발급
토큰을 이용해 사용자의 인증 상태 유지
JWT를 검증하여 인증된 사용자만 특정 API 요청 가능

다음 글에서는 Flask에서 Refresh Token을 이용해 JWT 자동 갱신하는 방법을 알아보겠습니다! 🚀

 

 

 

[PYTHON] Flask로 로그인 기능 구현하기 (세션 활용)

Flask로 로그인 기능 구현하기 (세션 활용)이전 글에서는 Flask를 활용한 웹 애플리케이션 개발 및 데이터베이스 연동을 배웠습니다.이번 글에서는 사용자 로그인 기능을 구현해 보겠습니다.로그

englishforkid.tistory.com

 

 

[파이썬 자격증] 데이터분석 준전문가(ADsP)란?

데이터분석 준전문가(ADsP)란? **데이터분석 준전문가(ADsP: Advanced Data Analytics Semi-Professional)**는 한국데이터산업진흥원(K-DATA)에서 주관하는 국가공인 데이터 분석 자격증입니다. ADsP는 데이터 활

englishforkid.tistory.com

 

 

[PYTHON] 파이썬 기초: 변수와 데이터 타입 이해하기

파이썬 기초: 변수와 데이터 타입 이해하기 파이썬을 배우면서 가장 먼저 익혀야 할 개념 중 하나가 변수(variable)와 데이터 타입(data type) 입니다. 변수를 사용하면 데이터를 저장하고 조작할 수

englishforkid.tistory.com