python中django实现验证码的功能实例代码
《Python中Django实现验证码的功能实例代码》
在Web开发中,验证码是防止恶意攻击(如暴力破解、机器人注册)的重要安全机制。Django作为Python最流行的Web框架之一,提供了灵活的方式实现验证码功能。本文将通过完整实例代码,详细讲解如何在Django项目中集成图形验证码和短信验证码,涵盖生成、验证及前后端交互的全流程。
一、图形验证码实现
图形验证码通过生成包含随机字符的图片,要求用户输入图片中的内容以验证身份。Django中可通过第三方库或自定义实现。
1. 安装依赖库
使用captcha
库(推荐)或Pillow
+自定义生成:
pip install django-simple-captcha pillow
# 或仅安装Pillow(自定义实现时)
pip install pillow
2. 配置settings.py
若使用django-simple-captcha
,需在INSTALLED_APPS
中添加:
INSTALLED_APPS = [
...
'captcha',
]
运行迁移命令生成数据库表(如需存储验证码记录):
python manage.py migrate
3. 自定义图形验证码生成器(不依赖第三方库)
创建utils/captcha.py
文件,实现验证码图片生成逻辑:
import random
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from django.core.cache import cache
def generate_captcha(request):
# 生成随机字符
chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' # 排除易混淆字符
captcha_text = ''.join(random.choices(chars, k=4))
# 创建图片
image = Image.new('RGB', (120, 40), color=(255, 255, 255))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('arial.ttf', 28) # 需确保字体文件存在
# 绘制字符(添加干扰线)
for i in range(4):
draw.text((10 + i*25, 5), captcha_text[i], fill=(0, 0, 0), font=font)
for _ in range(5):
x1 = random.randint(0, 120)
y1 = random.randint(0, 40)
x2 = random.randint(0, 120)
y2 = random.randint(0, 40)
draw.line(((x1, y1), (x2, y2)), fill=(0, 0, 0), width=1)
# 将图片转为BytesIO对象
buffer = BytesIO()
image.save(buffer, format='PNG')
captcha_image = buffer.getvalue()
# 存储验证码到缓存(Redis或内存)
cache_key = f'captcha_{request.session.session_key}'
cache.set(cache_key, captcha_text.lower(), timeout=300) # 5分钟有效期
return captcha_image, cache_key
4. 创建验证码视图
在views.py
中添加生成验证码的视图:
from django.http import HttpResponse
from django.views.decorators.http import require_GET
from .utils.captcha import generate_captcha
@require_GET
def get_captcha(request):
captcha_image, cache_key = generate_captcha(request)
response = HttpResponse(content_type='image/png')
response.write(captcha_image)
return response
5. 配置URL路由
在urls.py
中添加路由:
from django.urls import path
from . import views
urlpatterns = [
path('captcha/', views.get_captcha, name='captcha'),
]
6. 前端集成
在模板中通过img
标签加载验证码,并添加刷新按钮:
{% load static %}
7. 验证码验证逻辑
在表单提交时验证用户输入:
from django.core.cache import cache
def validate_captcha(request):
user_input = request.POST.get('captcha').lower()
cache_key = f'captcha_{request.session.session_key}'
stored_captcha = cache.get(cache_key)
if stored_captcha != user_input:
return False, '验证码错误'
cache.delete(cache_key) # 验证后删除
return True, '验证通过'
二、短信验证码实现
短信验证码通过发送随机数字到用户手机,常用于注册、登录等场景。需集成第三方短信服务(如阿里云、腾讯云)。
1. 安装短信SDK
以阿里云短信服务为例:
pip install aliyun-python-sdk-core aliyun-python-sdk-dysmsapi
2. 创建短信服务工具类
在utils/sms.py
中封装发送逻辑:
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from django.core.cache import cache
import random
class SMSService:
def __init__(self):
self.client = AcsClient(
'your_access_key_id',
'your_access_key_secret',
'default' # 区域ID
)
def send_sms(self, phone_number):
code = ''.join(random.choices('0123456789', k=6))
cache_key = f'sms_{phone_number}'
cache.set(cache_key, code, timeout=300) # 5分钟有效期
request = CommonRequest()
request.set_accept_format('json')
request.set_domain('dysmsapi.aliyuncs.com')
request.set_method('POST')
request.set_protocol_type('https')
request.set_version('2017-05-25')
request.set_action_name('SendSms')
request.add_query_param('PhoneNumbers', phone_number)
request.add_query_param('SignName', '你的签名')
request.add_query_param('TemplateCode', 'SMS_123456789') # 模板ID
request.add_query_param('TemplateParam', f'{{\"code\":\"{code}\"}}')
response = self.client.do_action_with_exception(request)
return response.decode() # 返回JSON字符串
def verify_code(self, phone_number, user_input):
cache_key = f'sms_{phone_number}'
stored_code = cache.get(cache_key)
if stored_code != user_input:
return False
cache.delete(cache_key)
return True
3. 创建短信发送视图
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from .utils.sms import SMSService
@require_POST
def send_sms_code(request):
phone_number = request.POST.get('phone')
if not phone_number:
return JsonResponse({'success': False, 'msg': '手机号不能为空'})
sms = SMSService()
try:
response = sms.send_sms(phone_number)
return JsonResponse({'success': True, 'msg': '验证码已发送'})
except Exception as e:
return JsonResponse({'success': False, 'msg': str(e)})
4. 配置URL路由
path('send-sms/', views.send_sms_code, name='send_sms'),
5. 前端集成(AJAX示例)
三、验证码安全优化
1. 限制验证码尝试次数:通过缓存记录失败次数,超过阈值后暂时禁用验证。
2. 验证码复杂度:增加字符长度、干扰线、扭曲变形等。
3. 短信频率限制:同一手机号每分钟仅允许发送一次。
4. HTTPS加密:确保验证码传输过程不被窃取。
四、完整示例:注册表单集成验证码
1. 修改注册表单视图:
from django.views.decorators.csrf import csrf_exempt
from .utils.captcha import validate_captcha
from .utils.sms import SMSService
@csrf_exempt
def register(request):
if request.method == 'POST':
# 验证图形验证码
captcha_valid, captcha_msg = validate_captcha(request)
if not captcha_valid:
return JsonResponse({'success': False, 'msg': captcha_msg})
# 验证短信验证码(假设已通过其他接口提交)
phone = request.POST.get('phone')
sms_code = request.POST.get('sms_code')
sms = SMSService()
if not sms.verify_code(phone, sms_code):
return JsonResponse({'success': False, 'msg': '短信验证码错误'})
# 注册逻辑...
return JsonResponse({'success': True, 'msg': '注册成功'})
五、常见问题解决
1. 验证码不显示:检查图片生成逻辑是否正确,确保响应头Content-Type: image/png
。
2. 缓存失效:确认Django缓存配置(如Redis)是否正常运行。
3. 短信发送失败:检查账号权限、模板审核状态及余额。
关键词:Django、验证码、图形验证码、短信验证码、Pillow、阿里云短信、缓存验证、Web安全
简介:本文详细介绍了在Django中实现图形验证码和短信验证码的完整流程,包括依赖安装、自定义生成器、前后端交互、安全优化及常见问题解决,提供了可复用的代码示例和最佳实践。