1. 장고 프로젝트에서 CAPTCHA 사용
CAPTCHA(Completely Automated Public Turing test to tell Computers and Humans Apart)는 컴퓨터와 인간을 구분하기 위한 자동화된 테스트입니다. 이는 악의적인 비밀번호 해킹, 투표 봇, 스팸 게시 등과 같은 문제를 방지하는 데 도움이 됩니다.
2. CAPTCHA의 종류
현재 사용되는 CAPTCHA의 주요 유형은 다음과 같습니다:
- 일반형: 문자, 숫자 또는 한글로 구성된 이미지 (대체로 4자리)
- 질문-답변형: 간단한 수학 문제 (예: 3+3=?)
- 드래그-앤-드롭형: 이미지를 맞추기 위해 특정 위치로 드래그
- 클릭형: 지정된 순서대로 이미지의 특정 부분 클릭
3. CAPTCHA 작동 원리
CAPTCHA의 기본 동작 과정은 다음과 같습니다:
- 클라이언트가 CAPTCHA 요청을 보냄
- 서버는 CAPTCHA와 정답을 생성
- 서버는 세션에 정답 저장
- 클라이언트에게 CAPTCHA 이미지 반환
- 사용자가 CAPTCHA를 확인하고 입력 후 서버로 제출
- 서버는 세션의 정답과 비교하여 검증
4. 장고 프로젝트에서 CAPTCHA 구현
아래 예제에서는 4자리 문자로 된 일반 CAPTCHA를 구현합니다.
4.1 로그인 기능 설정
먼저 기본 로그인 시스템을 설정합니다.
# views.py
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
@login_required(login_url='auth_app:login')
def home(request):
return render(request, 'auth_app/home.html')
def user_logout(request):
auth.logout(request)
return redirect('auth_app:login')
def user_login(request):
if request.method == 'GET':
error = request.session.pop('error', None)
return render(request, 'auth_app/login.html', {'error': error})
username = request.POST.get('username')
password = request.POST.get('password')
user = auth.authenticate(username=username, password=password)
if user:
auth.login(request, user)
return redirect('auth_app:home')
else:
request.session['error'] = '잘못된 사용자 정보입니다.'
return redirect('auth_app:login')
4.2 CAPTCHA 이미지 생성
Pillow 라이브러리를 사용하여 CAPTCHA 이미지를 생성합니다.
# utils/captcha_generator.py
import os
import random
import string
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
def generate_random_string(length=4):
return ''.join(random.choices(string.ascii_letters + string.digits, k=length))
def create_captcha_image():
image = Image.new('RGB', (200, 50), color=(255, 255, 255))
font_path = os.path.join(os.path.dirname(__file__), 'arial.ttf') # 폰트 파일 경로 수정 필요
font = ImageFont.truetype(font_path, size=40)
draw = ImageDraw.Draw(image)
text = generate_random_string()
for i, char in enumerate(text):
draw.text((50 * i + 10, 10), char, font=font, fill=(random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255)))
buffer = BytesIO()
image.save(buffer, 'PNG')
return buffer.getvalue(), text
4.3 CAPTCHA 기능 추가
로그인 페이지에 CAPTCHA 기능을 추가합니다.
# views.py
from django.http import HttpResponse
from .utils.captcha_generator import create_captcha_image
def captcha(request):
image_data, code = create_captcha_image()
request.session['captcha_code'] = code
return HttpResponse(image_data, content_type='image/png')
def user_login(request):
if request.method == 'POST':
input_code = request.POST.get('captcha').strip().lower()
stored_code = request.session.get('captcha_code', '').lower()
if input_code != stored_code:
request.session['error'] = 'CAPTCHA가 일치하지 않습니다.'
return redirect('auth_app:login')
# 기존 로직 처리...
4.4 HTML 코드 수정
로그인 폼에 CAPTCHA 필드를 추가합니다.
<form method="post">
{% csrf_token %}
<label>사용자명:</label>
<input type="text" name="username"><br>
<label>비밀번호:</label>
<input type="password" name="password"><br>
<label>CAPTCHA:</label>
<input type="text" name="captcha">
<img src="{% url 'auth_app:captcha' %}" onclick="this.src='{% url 'auth_app:captcha' %}?r=' + Math.random();"><br>
<button type="submit">로그인</button>
</form>