Python에서 JWT(유효한 웹 토큰)를 생성하고 검증하는 완벽한 가이드

Python에서 JWT(JSON Web Token)를 활용한 인증과 보안 향상에 대해, 생성부터 검증까지 자세히 설명합니다. 본 기사에서는 Python 라이브러리를 활용하여 JWT를 이용한 인증 프로세스를 완전히 이해할 수 있도록 기본 개념부터 구현 예제, 보안 대책까지를 포괄적으로 다룹니다. 웹 애플리케이션 및 API 개발에서 신뢰성 높은 인증 기능을 구축하기 위한 지식을 깊이 있게 배워봅시다.

JWT의 기본 개념과 구조


JWT(JSON Web Token)는 웹 인증에서 널리 사용되는 토큰 형식 중 하나입니다. JWT는 클라이언트와 서버 간에 정보를 안전하게 전달하기 위한 표준 규격(RFC 7519)을 기반으로 하며, 서명을 통한 변조 방지 기능을 제공합니다.

JWT의 구조


JWT는 점(.)으로 구분된 다음 세 가지 부분으로 구성됩니다:

  1. 헤더
  • 토큰의 종류(예: JWT)와 서명 알고리즘(예: HS256)을 지정합니다.
   {
       "alg": "HS256",
       "typ": "JWT"
   }
  1. 페이로드
  • 토큰에 포함할 데이터(클레임)를 JSON 형식으로 작성합니다.
   {
       "sub": "1234567890",
       "name": "John Doe",
       "admin": true
   }
  1. 서명
  • 헤더와 페이로드를 기반으로 비밀키나 공개키로 생성된 서명. 변조 방지 역할을 합니다.

JWT의 동작 원리

  1. 클라이언트가 로그인 시 인증 정보를 전송하면, 서버는 그 정보를 바탕으로 JWT를 생성합니다.
  2. 생성된 JWT는 클라이언트에게 전송되며, 보통 쿠키나 HTTP 헤더에 저장됩니다.
  3. 클라이언트는 요청 시마다 JWT를 서버에 전송하고, 서버는 토큰을 검증하여 요청을 허용합니다.

이 프로세스를 통해 상태 없는 인증이 가능하며, 확장성과 보안성이 향상됩니다.

Python에서 JWT 라이브러리 선택

Python에서 JWT를 다룰 때, 유용한 라이브러리들이 제공됩니다. 각각의 라이브러리는 특징이 있으며, 프로젝트의 요구사항에 맞는 적절한 라이브러리를 선택하는 것이 중요합니다.

주요 라이브러리

  1. PyJWT
  • 가장 일반적이고 가벼운 라이브러리. JWT의 생성과 검증을 쉽게 할 수 있습니다.
  • 공식 사이트: PyJWT GitHub
  • 특징:
    • 간단한 API로 사용이 용이
    • HMAC(HS256, HS512)나 RSA(RS256, RS512) 등의 다양한 서명 알고리즘 지원
  • 설치:
    bash pip install pyjwt
  1. Authlib
  • OAuth2와 OpenID Connect와 같은 고급 인증 프레임워크를 지원. JWT도 지원합니다.
  • 공식 사이트: Authlib
  • 특징:
    • 고급 보안 기능
    • 토큰 처리에 특화
  • 설치:
    bash pip install authlib
  1. python-jose
  • JSON Web Token, JSON Web Signature (JWS), JSON Web Encryption (JWE)를 지원합니다.
  • 특징:
    • 암호화(JWE)의 지원이 뛰어남
    • 고급 커스터마이징 가능
  • 설치:
    bash pip install python-jose

라이브러리 선택 기준

  • 단순 인증 용도: PyJWT가 최적. 가볍고 직관적으로 사용 가능.
  • 고급 인증 흐름: OAuth나 OpenID Connect를 채택할 경우 Auth lib 추천.
  • 암호화 필요: 토큰 암호화가 요구될 경우 python-jose 선택.

프로젝트의 규모나 보안 요구 사항에 따라 이러한 라이브러리를 적절히 사용하여 효율적으로 JWT를 활용할 수 있습니다.

Python으로 JWT 생성 구현

JWT를 생성하려면, 적절한 Python 라이브러리를 활용하여 효율적으로 구현할 수 있습니다. 여기서는 가장 많이 사용되는 PyJWT 라이브러리를 예로 들어 JWT 생성의 기본적인 절차를 설명합니다.

PyJWT를 사용한 기본적인 JWT 생성

다음 코드는 PyJWT를 사용하여 JWT를 생성하는 예제입니다.

import jwt
import datetime

# 비밀키 설정
SECRET_KEY = "your-secret-key"

# 페이로드 작성
payload = {
    "sub": "1234567890",       # 사용자 ID 등 식별자
    "name": "John Doe",        # 임의의 사용자 정보
    "iat": datetime.datetime.utcnow(),  # 토큰 발행 시간
    "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)  # 유효 기간(1시간 후)
}

# 토큰 생성
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")

print("Generated JWT:", token)

코드 설명

  1. 비밀키 설정
  • 토큰 서명에 사용할 비밀키를 설정합니다. 서버 내에서 안전하게 관리해야 합니다.
  1. 페이로드 작성
  • subname 등의 클레임을 포함합니다.
  • 필요에 따라 발행 시간(iat)이나 유효 기간(exp)을 설정합니다.
  1. 토큰 생성
  • jwt.encode를 사용하여 페이로드를 인코딩하고 토큰을 생성합니다.
  • 서명 알고리즘으로는 일반적으로HS256이나RS256이 사용됩니다.

RSA 서명을 사용한 JWT 생성

공개키와 비밀키를 사용하여 서명을 하는 예제를 아래에示시합니다.

import jwt

# RSA 비밀키와 공개키
private_key = """-----BEGIN RSA PRIVATE KEY-----
...(비밀키 내용)...
-----END RSA PRIVATE KEY-----"""
public_key = """-----BEGIN PUBLIC KEY-----
...(공개키 내용)...
-----END PUBLIC KEY-----"""

# 페이로드 작성
payload = {
    "sub": "1234567890",
    "name": "John Doe",
    "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}

# RSA 서명으로 토큰 생성
token = jwt.encode(payload, private_key, algorithm="RS256")
print("Generated JWT with RSA:", token)

주의사항

  1. 비밀키 관리
  • 비밀키는 철저히 관리하며, 제3자에게 유출되지 않도록 주의해야 합니다.
  1. 유효 기간 설정
  • exp을 설정하여 토큰의 유효 기간을 제한하는 것은 보안상 필수입니다.
  1. 토큰 크기
  • 페이로드에 필요 이상의 정보를 포함하면 토큰의 크기가 커져 통신 효율이 저하될 수 있습니다.

이 코드 예제를 활용하여 필요에 맞는 JWT를 생성하고, 안전한 인증 시스템을 구축합시다.

JWT의 페이로드에 포함할 데이터 설계

JWT의 페이로드(Payload)에는 사용자 정보나 토큰의 속성을 기록합니다. 페이로드의 설계는 토큰의 크기와 보안에 영향을 미치므로 적절하게 설계하는 것이 중요합니다.

페이로드의 기본 구성

JWT의 페이로드에는 다음 세 가지 종류의 클레임(claim)을 포함할 수 있습니다:

  1. 등록된 클레임
  • 규격에 따라 표준화된 클레임. 특정 의미가 있으므로 적절히 사용합니다.
  • 주요 예시:
    • iss(발행자): 토큰을 발행한 주체를 나타냅니다.
    • sub(주체): 토큰의 대상이 되는 주체를 나타냅니다 (예: 사용자 ID).
    • aud(수신자): 토큰의 수신자를 나타냅니다 (예: 특정 서비스명).
    • exp(유효 기간): 토큰의 유효 기간을 UNIX 타임스탬프 형식으로 지정합니다.
    • iat(발행 시간): 토큰이 발행된 시간을 UNIX 타임스탬프 형식으로 지정합니다.
  1. 공개 클레임
  • 애플리케이션 고유의 데이터를 정의할 수 있습니다.
  • 다른 시스템과의 충돌을 피하기 위해 네임스페이스를 사용합니다 (예: namespace/attribute).
  1. 비공개 클레임
  • 애플리케이션 내에서만 사용되는 데이터. 네임스페이스를 필요로 하지 않습니다.

설계 시의 베스트 프랙티스

필요 최소한의 데이터 포함


JWT는 기본적으로 Base64로 인코딩된 문자열로, 토큰의 크기가 통신 효율에 영향을 미칩니다. 따라서 페이로드에는 인증이나 권한 부여에 필요한 데이터만 포함합니다.

{
    "sub": "1234567890",
    "name": "John Doe",
    "roles": ["admin", "user"]
}

데이터의 민감성 고려


JWT는 서명에 의해 변조 방지가 되지만, 암호화된 것은 아닙니다. 따라서 다음과 같은 기밀 정보를 페이로드에 포함하는 것은 피해야 합니다:

  • 비밀번호
  • 신용카드 정보
  • 개인 식별 정보(PII: Personally Identifiable Information)

토큰의 유효 기간 명확히 설정


페이로드에는 반드시exp 클레임을 설정하고, 유효 기간을 짧게 설정하여 보안 리스크를 줄입니다.

JWT 페이로드 설계 예시


다음은 실제적인 JWT 페이로드의 예입니다:

{
    "iss": "https://example.com",   // 발행자
    "sub": "user123",               // 사용자 ID
    "aud": "https://myapi.example.com", // 수신자
    "exp": 1701209952,              // 유효 기간 (UNIX 타임스탬프)
    "iat": 1701206352,              // 발행 시각
    "roles": ["user", "admin"],     // 사용자 권한
    "preferences": {
        "theme": "dark",            // 사용자 설정
        "notifications": true
    }
}

토큰 크기 고려


페이로드가 커지면, 토큰 전체 크기도 증가하고 다음과 같은 문제가 발생할 수 있습니다:

  • HTTP 헤더로 전송할 때 요청 크기 증가
  • 모바일 장치에서 데이터 사용량 증가

필요에 따라 사용자 정의 클레임을 줄여 토큰을 가볍게 만드는 방법을 고려합시다.

요약


페이로드 설계는 토큰의 효율성과 보안을 유지하기 위해 중요합니다. 표준 클레임을 활용하고 애플리케이션에 필요한 정보만 포함하여 최적의 토큰 설계를 구현합시다.

비밀키와 공개키를 사용한 서명의 원리

JWT의 보안을 확보하는 데 있어 서명은 중요한 역할을 합니다. 특히 공개키와 비밀키를 사용하는 서명(비대칭 서명)은 변조 방지와 신뢰성 확보에 적합합니다. 여기에서는 서명의 원리와 Python에서의 구현 방법을 설명합니다.

서명의 원리

JWT의 서명에는 다음과 같은 두 가지 종류가 있습니다:

  1. 대칭 서명(HMAC)
  • 하나의 비밀키를 공유하여 서명과 검증을 수행합니다.
  • 간단하고 빠르지만, 키 관리가 문제가 될 수 있습니다.
  • 사용 알고리즘 예시: HS256, HS512
  1. 비대칭 서명(RSA, ECDSA)
  • 비밀키로 서명을 하고, 공개키로 검증합니다.
  • 서버 간 또는 제3자 기관을 통한 거래에 적합합니다.
  • 사용 알고리즘 예시: RS256, ES256

비대칭 서명의 장점:

  • 비밀키를 철저히 관리하면, 공개키가 유출되어도 안전성을 유지할 수 있습니다.
  • 검증자가 여러 명일 경우에 적합합니다.

Python에서 RSA 서명 구현

비대칭 서명을 사용한 JWT 생성과 검증을, Python의 PyJWT 라이브러리로 수행하는 예제를 보여드립니다.

서명 키 준비


비밀키와 공개키를 사전에 생성해 둡니다.

openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem

JWT 생성


비밀키를 사용하여 JWT를 생성합니다.

import jwt
import datetime

# 비밀키 읽기
with open("private.pem", "r") as key_file:
    private_key = key_file.read()

# 페이로드 작성
payload = {
    "sub": "1234567890",
    "name": "John Doe",
    "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1)
}

# 서명된 JWT 생성
token = jwt.encode(payload, private_key, algorithm="RS256")
print("Generated JWT:", token)

JWT 검증


공개키를 사용하여 JWT를 검증합니다.

# 공개키 읽기
with open("public.pem", "r") as key_file:
    public_key = key_file.read()

# JWT 검증
try:
    decoded = jwt.decode(token, public_key, algorithms=["RS256"])
    print("Decoded Payload:", decoded)
except jwt.ExpiredSignatureError:
    print("The token has expired.")
except jwt.InvalidTokenError:
    print("The token is invalid.")

서명 알고리즘 선택 기준

  • HS256(HMAC): 단순한 서버 측 인증 시스템에 적합
  • RS256(RSA): 서버 간 통신이나 외부 시스템과의 연동이 필요한 경우 적합
  • ES256(ECDSA): 더 가벼운 공개키 서명을 원하는 경우 유효

베스트 프랙티스

  1. 비밀키 철저 관리
  • 비밀키는 철저히 보호하고, 접근 제한을 철저히 해야 합니다.
  1. 유효 기간 설정
  • 토큰의exp 클레임을 이용해 유효 기간을 짧게 설정합니다.
  1. 알고리즘 선택 명시
  • 서명 알고리즘을 반드시 명시적으로 지정하고, 기본값을 사용하지 않도록 합니다.

요약


비밀키와 공개키를 사용한 서명은 높은 보안을 실현하는 데 중요합니다. RSA 서명은 서버 간의 거래나 공개키의 분산이 필요한 시스템에 특히 유효합니다. Python을 이용한 구현 예제를 바탕으로, 안전하고 신뢰성 높은 인증 시스템을 구축합시다.

JWT 검증 프로세스

JWT를 사용한 인증에서는 토큰의 유효성을 확인하는 “검증 프로세스”가 중요합니다. 검증을 통해 토큰이 변조되지 않았는지, 올바른 비밀키 또는 공개키로 서명되었는지, 유효기간 내에 있는지 등을 확인합니다. 여기서는 JWT 검증 절차와 Python에서의 구현 예를 설명합니다.

JWT 검증의 기본 프로세스

  1. 서명 검증
  • 토큰이 올바른 비밀키 또는 공개키로 서명되었는지 확인합니다. 서명이 일치하지 않으면 토큰은 무효입니다.
  1. 유효기간 확인
  • 페이로드의exp 클레임을 확인하고, 토큰이 유효기간 내에 있는지 검증합니다. 만료된 토큰은 무효입니다.
  1. 기타 클레임 검증
  • 필요에 따라, iss (발급자) 또는 aud (수신자) 등의 클레임을 확인합니다. 이를 통해 특정 토큰이 적절한 시스템에서만 사용되도록 보장합니다.

Python에서의 JWT 검증

다음은 PyJWT 라이브러리를 사용하여 JWT를 검증하는 예시입니다.

기본 검증

import jwt

# 공개키 또는 비밀키 지정
SECRET_KEY = "your-secret-key"

# 검증할 토큰
token = "your.jwt.token"

# JWT 디코딩 및 검증
try:
    decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]])
    print("Verified Payload:", decoded)
except jwt.ExpiredSignatureError:
    print("The token has expired.")
except jwt.InvalidTokenError:
    print("The token is invalid.")

RS256 (공개키)로 검증

비대칭 서명(RS256)을 사용할 경우, 공개키를 사용하여 서명을 검증합니다.

# 공개키 읽기
with open("public.pem", "r") as key_file:
    public_key = key_file.read()

# JWT 디코딩 및 검증
try:
    decoded = jwt.decode(token, public_key, algorithms=["RS256"]])
    print("Verified Payload:", decoded)
except jwt.ExpiredSignatureError:
    print("The token has expired.")
except jwt.InvalidTokenError:
    print("The token is invalid.")

검증 시 추가 클레임 확인

다음과 같이 클레임을 지정하여 검증을 강화할 수 있습니다:

decoded = jwt.decode(
    token,
    SECRET_KEY,
    algorithms=["HS256"],
    options={"verify_exp": True},  # 유효기간 검증 활성화
    audience="https://myapi.example.com",  # 수신자 검증
    issuer="https://example.com"  # 발급자 검증
)

검증 시 주의 사항

  1. 알고리즘 지정
  • 검증 시 반드시 사용할 알고리즘을 명시해야 합니다. None이나 예상치 못한 알고리즘이 사용되면 보안 리스크가 증가합니다.
  1. 만료된 토큰 처리
  • 유효기간이 지난 토큰(ExpiredSignatureError)은 재로그인이나 토큰 갱신을 유도해야 합니다.
  1. 토큰 출처 확인
  • 토큰이 신뢰할 수 있는 출처에서 제공되었는지 확인해야 합니다.

토큰 검증 플로우 전체도

  1. 토큰 수신
  2. 토큰 구조(Header, Payload, Signature) 확인
  3. 헤더의 알고리즘 확인 및 서명 검증
  4. 페이로드의 exp 또는 iss 확인
  5. 검증에 성공한 경우에만 요청 승인

요약

JWT 검증은 인증 프로세스의 핵심을 담당합니다. 올바른 키를 사용한 서명 검증과 유효기간 체크를 통해 신뢰성 높은 안전한 시스템을 구축할 수 있습니다. Python을 활용한 구현 예시를 참고하여, 안전한 JWT 검증 프로세스를 도입해 보세요.

토큰 유효기간과 리프레시 구현

JWT를 사용할 때, 유효기간 설정과 리프레시 토큰 도입은 보안을 강화하는 데 필수적입니다. 이 절에서는 유효기간 설정 방법과 토큰 리프레시를 Python으로 구현하는 절차를 설명합니다.

유효기간 설정

JWT의 exp (expiration) 클레임을 사용하여 유효기간을 설정합니다. 아래는 Python에서의 구현 예시입니다.

import jwt
import datetime

# 비밀키 설정
SECRET_KEY = "your-secret-key"

# 페이로드에 유효기간 추가
payload = {
    "sub": "1234567890",       # 사용자 ID
    "name": "John Doe",        # 사용자 정보
    "iat": datetime.datetime.utcnow(),  # 발행 시간
    "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=30)  # 30분간 유효
}

# 토큰 생성
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
print("Access Token:", token)

주의사항

  • 유효기간은 짧게(5분~30분 정도) 설정하여, 토큰이 도난당했을 경우 리스크를 줄일 수 있습니다.
  • 토큰이 만료되면 사용자에게 재인증 또는 리프레시를 요구하는 시스템을 구현합니다.

리프레시 토큰 설계

리프레시 토큰은 액세스(메인) 토큰과는 별도로 발행되며, 만료된 액세스 토큰을 갱신하는 데 사용됩니다. 리프레시 토큰의 특징:

  1. 유효기간이 길다 (수일~수주)
  2. 서버 측에서 보관 및 관리되는 경우가 많다

리프레시 토큰 발급 예

# 리프레시 토큰 페이로드
refresh_payload = {
    "sub": "1234567890",       # 사용자 ID
    "iat": datetime.datetime.utcnow(),  # 발행 시간
    "exp": datetime.datetime.utcnow() + datetime.timedelta(days=7)  # 7일간 유효
}

# 리프레시 토큰 생성
refresh_token = jwt.encode(refresh_payload, SECRET_KEY, algorithm="HS256")
print("Refresh Token:", refresh_token)

리프레시 프로세스 구현

토큰이 만료되면, 리프레시 토큰을 사용하여 새로운 액세스 토큰을 생성합니다.

# 리프레시 토큰 디코딩 및 새로운 액세스 토큰 발급
try:
    decoded_refresh = jwt.decode(refresh_token, SECRET_KEY, algorithms=["HS256"]])

    # 새로운 액세스 토큰 발급
    new_access_payload = {
        "sub": decoded_refresh["sub"],
        "name": "John Doe",
        "iat": datetime.datetime.utcnow(),
        "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
    }
    new_access_token = jwt.encode(new_access_payload, SECRET_KEY, algorithm="HS256")
    print("New Access Token:", new_access_token)
except jwt.ExpiredSignatureError:
    print("The refresh token has expired.")
except jwt.InvalidTokenError:
    print("The refresh token is invalid.")

리프레시 토큰 보안 고려 사항

  1. 서버 측 관리
  • 리프레시 토큰은 데이터베이스나 메모리 상에서 서버 측에 저장하여 도난 및 변조를 방지합니다.
  1. 일회용 사용
  • 사용된 리프레시 토큰은 무효화하여 세션 하이재킹을 방지합니다.
  1. 사용 시 재인증
  • 리프레시 토큰 사용 시 추가 사용자 인증을 요구하여 보안을 강화합니다.

리프레시 토큰 API 설계 예

토큰 갱신 API 설계 예:

  1. 클라이언트가 만료된 액세스 토큰과 리프레시 토큰을 전송
  2. 서버가 리프레시 토큰을 검증
  3. 유효한 경우 새로운 액세스 토큰을 발급하여 클라이언트에게 반환

API 엔드포인트 예

POST /api/token/refresh
Authorization: Bearer {refresh_token}

응답 예:

{
    "access_token": "new_access_token",
    "expires_in": 1800
}

요약

JWT의 유효기간과 리프레시 토큰을 적절히 구현함으로써 보안을 확보하면서도 사용자 경험을 향상시킬 수 있습니다. 유효기간 단축과 리프레시 토큰의 결합을 통해 신뢰성 높은 인증 시스템을 구축합시다.

보안 리스크와 그 대응책

JWT는 인증 및 세션 관리에 유용하지만, 부적절한 구현이나 관리로 인한 보안 리스크가 존재합니다. 이 절에서는 JWT와 관련된 일반적인 리스크 와 그 대응책에 대해 설명합니다.

일반적인 보안 리스크

1. 비밀키 유출


JWT의 서명 키가 유출되면, 불법적인 토큰 생성이나 시스템 장악이 가능해집니다.

대응책:

  • 비밀키는 안전한 환경(예: 환경 변수, 비밀 관리 서비스)에 저장합니다.
  • 정기적으로 키를 교체(로테이션)합니다.

2. 토큰 변조


서명이 적절하게 검증되지 않으면, 토큰 내용이 변조될 위험이 있습니다.

대응책:

  • 항상 토큰 서명을 검증합니다.
  • 알고리즘을 명시적으로 지정하고, 불법적인 알고리즘(예: none)을 허용하지 않습니다.

3. 토큰 도난


토큰이 도난당하면, 도둑이 정당한 사용자처럼 행동할 수 있게 됩니다.

대응책:

  • HTTPS를 사용하여 통신을 암호화합니다.
  • 안전한 저장소에 토큰을 저장합니다(예: HttpOnly 속성의 쿠키).
  • 토큰 유효기간을 짧게 설정합니다.

4. 토큰 리플레이 공격


도난당한 토큰이 재사용되어 동일 세션이 탈취될 위험이 있습니다.

대응책:

  • 각 토큰에 고유 식별자(jti 클레임)를 설정하고, 서버 측에서 토큰의 사용 내역을 추적합니다.
  • 사용된 토큰을 블랙리스트에 등록합니다.

5. 무효화 어려움


JWT는 상태가 없는 방식이므로, 한 번 발행된 토큰을 무효화하는 메커니즘이 없을 수 있습니다.

대응책:

  • 리프레시 토큰과 블랙리스트 메커니즘을 결합하여 무효화를 구현합니다.
  • 토큰의 유효기간을 짧게 설정하고, 자주 갱신합니다.

Python에서의 구체적인 대응책 구현

1. 키 관리


비밀키를 환경변수에서 가져오는 예시:

import os

SECRET_KEY = os.getenv("JWT_SECRET_KEY")
if not SECRET_KEY:
    raise ValueError("Secret key must be set!")

2. 알고리즘 명시


불법 알고리즘을 방지하기 위해 사용할 알고리즘을 지정:

import jwt

# 토큰 검증
decoded = jwt.decode(token, SECRET_KEY, algorithms=["HS256"]])

3. HTTPS 사용


Flask 등에서 HTTPS를 강제하는 예:

from flask import Flask

app = Flask(__name__)
app.config['PREFERRED_URL_SCHEME'] = 'https'

4. 리플레이 공격 방지


고유 식별자(jti)를 설정하고 데이터베이스에서 사용 내역을 기록:

import uuid

payload = {
    "sub": "1234567890",
    "jti": str(uuid.uuid4()),  # 고유 ID
    "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=30)
}

5. 블랙리스트 구현


Redis를 사용한 토큰 무효화 예시:

import redis

# Redis 클라이언트
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)

# 토큰 무효화
redis_client.setex("blacklist:" + token, 1800, "true")  # 1800초 후 무효화

기타 추천 사항

  • 교차 사이트 스크립팅(XSS) 방지
    HttpOnly 쿠키를 사용하여 토큰을 보호합니다.
  • 로그 모니터링
    불법적인 토큰 사용을 감지하기 위해 토큰 발급 및 검증 로그를 기록합니다.
  • 요약

    JWT 사용에는 많은 장점이 있지만, 보안 대책을 소홀히 하면 심각한 리스크를 초래할 수 있습니다. 비밀키의 적절한 관리, 토큰 서명 검증, 유효기간 단축 등을 통해 소개된 대책들을 반영하여 안전한 인증 시스템을 구축합시다.

    요약

    이 글에서는 Python을 사용한 JWT(JSON Web Token)의 생성과 검증에 대해, 기본 개념부터 구현 방법, 보안 대책까지를 설명했습니다.

    JWT는 상태가 없고 확장 가능한 인증 시스템을 구축하는 데 매우 유효한 수단이지만, 비밀키 관리, 토큰 유효기간, 리프레시 토큰 설계 등 보안적인 고려가 필수적입니다.

    Python 라이브러리를 활용하여 안전하고 효율적인 시스템을 구축함으로써, 신뢰할 수 있는 사용자 인증과 세션 관리를 실현합시다.