django-simple-captcha验证码的使用

第三方库:django-simple-captcha

简单使用步骤

(一)安装配置captcha:

1. 【Terminal】使用命令行安装

pip install django-simple-captcha

2. 把captcha添加到Django项目下的settings.py文件已安装app中
INSTALLED_APPS = [
   ……
    'captcha',
]
3. 【Terminal】迁移验证码所需数据库

python manage.py migrate

  • 数据库迁移相关命令:
    python manage.py makemigrations 是用于检测app/models.py的改动,console会告知create model xxx
    python manage.py migrate将上述改动翻译成sql并去数据库执行

  • 验证码模型源码地址:venv/Lib/site-packages/captcha/models.py

    from captcha.conf import settings as captcha_settings
    from django.db import models
    from django.utils import timezone
    from six import python_2_unicode_compatible
    from django.utils.encoding import smart_text
    import datetime
    import hashlib
    import logging
    import random
    import time
    
    
    # Heavily based on session key generation in Django
    # Use the system (hardware-based) random number generator if it exists.
    if hasattr(random, 'SystemRandom'):
        randrange = random.SystemRandom().randrange
    else:
        randrange = random.randrange
    MAX_RANDOM_KEY = 18446744073709551616     # 2 << 63
    
    logger = logging.getLogger(__name__)
    
    
    @python_2_unicode_compatible
    class CaptchaStore(models.Model):
        challenge = models.CharField(blank=False, max_length=32)
        response = models.CharField(blank=False, max_length=32)
        hashkey = models.CharField(blank=False, max_length=40, unique=True)
        expiration = models.DateTimeField(blank=False)
    
        def save(self, *args, **kwargs):
            self.response = self.response.lower()
            if not self.expiration:
                self.expiration = timezone.now() + datetime.timedelta(minutes=int(captcha_settings.CAPTCHA_TIMEOUT))
            if not self.hashkey:
                key_ = (
                    smart_text(randrange(0, MAX_RANDOM_KEY)) +
                    smart_text(time.time()) +
                    smart_text(self.challenge, errors='ignore') +
                    smart_text(self.response, errors='ignore')
                ).encode('utf8')
                self.hashkey = hashlib.sha1(key_).hexdigest()
                del(key_)
            super(CaptchaStore, self).save(*args, **kwargs)
    
        def __str__(self):
            return self.challenge
    
        def remove_expired(cls):
            cls.objects.filter(expiration__lte=timezone.now()).delete()
        remove_expired = classmethod(remove_expired)
    
        @classmethod
        def generate_key(cls, generator=None):
            challenge, response = captcha_settings.get_challenge(generator)()
            store = cls.objects.create(challenge=challenge, response=response)
    
            return store.hashkey
    
        @classmethod
        def pick(cls):
            if not captcha_settings.CAPTCHA_GET_FROM_POOL:
                return cls.generate_key()
    
            def fallback():
                logger.error("Couldn't get a captcha from pool, generating")
                return cls.generate_key()
    
            # Pick up a random item from pool
            minimum_expiration = timezone.now() + datetime.timedelta(minutes=int(captcha_settings.CAPTCHA_GET_FROM_POOL_TIMEOUT))
            store = cls.objects.filter(expiration__gt=minimum_expiration).order_by('?').first()
    
            return (store and store.hashkey) or fallback()
    
        @classmethod
        def create_pool(cls, count=1000):
            assert count > 0
            while count > 0:
                cls.generate_key()
                count -= 1
    
     
    
  • 数据库表结构如下:
    在这里插入图片描述

  • Django的captcha没有用session对验证码进行存储,而是在数据库中生成一张表进行存储页面加载时数据库生成一条关于验证码的记录。当提交表单时post到服务器,此时服务器验证captcha_captchastore表中的hashkey对应的response是否与输入的验证码一致。(看起来验证过程是自动完成的,在封装好的第三方库,所以后台代码也不需要处理验证码的验证工作)

4. 添加captcha到urls.py中(在项目urls或者app的urls均可)
	urlpatterns = [
		path ('captcha/', include ('captcha.urls')),  # 验证码 		
	]
  • 文档:

    urlpatterns += [
        url(r'^captcha/', include('captcha.urls')),
    ]
    
  • 补充url和path的区别:

    PATH(2.0):from django.urls import path——第三方框架/模块
    URL(1.0):from django.urls import url——自定义模块

(二)将验证码添加到表单

1. 定义验证码表单
  • 新建forms.py文件在app目录下(即models.py同级目录)
  • 可以选继承Form或者modelForm
#forms.py

from django import forms
from captcha.fields import CaptchaField

class CaptchaTestForm(forms.Form):
    captcha = CaptchaField()
2. 验证表单方法定义
# views.py

from user.forms import CaptchaTestForm
from django.shortcuts import render
def some_view(request):
    if request.POST:
        form = CaptchaTestForm(request.POST)
        # Validate the form: the captcha field will automatically
        # check the input
        if form.is_valid():
            human = True
    else:
        form = CaptchaTestForm()
    return render(request,'captcha.html', locals())
  • 必须import定义的表单和render(我的app名是user)
  • 文档用的render_to_response在现在新的django里面已经不支持,换成render可以使用
  • locals()返回函数执行到此节点内的所有局部变量
3. 添加路由

将上面新增的some_view方法加到urls路由

# user/urls.py
urlpatterns = [
    path ('captcha/', include ('captcha.urls')),  # 验证码
    ……
    path('demo',views.some_view),
]
4. 定义前端页面
<!--captcha.html-->

<form method='POST'>
    {% csrf_token %}
    {{ form }}
    <input type="submit" />
    <button class='js-captcha-refresh'></button>
</form>
  • {% csrf_token %}不放在表单内,提交可能会产生错误
    在这里插入图片描述
  • CSRF -跨站请求伪造保护
  • 表单没有添加action操作,因此验证通过还是回到原页面,错误会有提示

(三)效果展示

页面展示验证码错误提示

参考文档:

部分问题

(一)前后端分离验证码如何传值

1.问题描述

一直不知道验证码在前后端分离的时候,接口设计怎么使用,比如需要传什么数据,但是前端传递入口又依赖于django的captcha库,后端才接触captcha,那前端要怎么作用呢?就做了一个像下面一样小白的测试,但是captcha_0(一段输入的哈希值吧)怎么前端怎么拿传给后台呢?
在这里插入图片描述

2.需求字段

登录表单定义了三个属性(见下个目录的代码),但是从控制台看有四个数据,验证码占两个:captcha_0(hashkey),captcha_1(用户输入)。

3.现有项目

项目结构大概如下(user是项目的app):
在这里插入图片描述

  • templates/user/login.html
<!--login.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div>
    <form action="/user/formlogin" method="post">
        {% csrf_token %}
         <!-- 登录表单 -->
        <div>
            {{ login_form.user_account.label_tag }}
            {{ login_form.user_account }}
        </div>
        <div>
            {{ login_form.password.label_tag }}
            {{ login_form.password }}
        </div>
         <!-- 验证码 -->
        <div>
            {{ login_form.captcha.errors }}
            {{ login_form.captcha.label_tag }}
            {{ login_form.captcha }}
        </div>
        <input type="submit" value="确定">
    </form>
</div>
</body>
</html>
  • user/forms.py
# forms.py
from django import forms
from captcha.fields import CaptchaField
from django.core.exceptions import ValidationError
from user.models import User


# 登录表单
class UserForm (forms.Form):
    user_account = forms.CharField (label="用户名", max_length=128, widget=forms.TextInput (attrs={'class': 'form-control'}))
    password = forms.CharField (label="密码", max_length=256,
                                widget=forms.PasswordInput (attrs={'class': 'form-control'}))
    captcha = CaptchaField (label='验证码')  # 图片验证码+输入框
  • user/views.py
# 用户登录,生成token
# 接收表单数据
# username 用户名
# password 密码
# user 通过输入的用户名获取的数据库用户
# url:user/formlogin
# 返回JSON数据
@csrf_exempt
def form_login(request):
    if request.method == "POST":
        login_form = UserForm (request.POST)  # 自定义登录表单
        if login_form.is_valid ():  # 确保用户名和密码都不为空
            username = login_form.cleaned_data['user_account']
            password = login_form.cleaned_data['password']
            print (username + password)
            try:
                user = User.objects.get (user_account=username)
            except:
                return HttpResponse (json.dumps ({'code': '301'}))  # 用户不存在
            if check_password (password, user.password):
                # print ('数据库密码是:' + user.password)
                temp = user
                token = token_op.create_token (temp)
                return HttpResponse (
                    json.dumps (
                        {
                            'code': '200',  # 成功状态码
                            'token': token,
                            'user_id': user.user_id,
                            'user_account': user.user_account,
                            'user_url': user.user_url,
                            'user_name': user.user_name,
                            'user_gender': user.user_gender,
                            'email': user.email,
                            'user_phone': user.user_phone,
                            'user_credit': user.user_credit,
                            'status': user.status,
                        }
                    )
                )
            else:
                return HttpResponse (json.dumps ({'code': '302'}))  # 密码不正确
        else:
            return HttpResponse (json.dumps ({'code': '402'}))  # 输入框未填完
    else:
        # login_form = UserForm ()
        # return HttpResponse (json.dumps ({'code': '404'}))  # 请求非POST类型
        return render(request, 'user/login.html', locals())
  • user/urls.py 添加路由
path ('formlogin', loginViews.form_login),  # html页面
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django使用django-simple-captcha生成验证码可以通过以下步骤现: 1. 安装django-simple-captcha库: 在终端中运行以下命令安装django-simple-captcha库: ``` pip install django-simple-captcha ``` 2. 在Django项目的`settings.py`文件中添加`captcha`应用: 打开`settings.py`文件,找到`INSTALLED_APPS`列表,将`'captcha'`添加到其中。 3. 运行数据库迁移: 在终端中运行以下命令,将`captcha`应用的数据库迁移到你的项目中: ``` python manage.py migrate captcha ``` 4. 在需要生成验证码的表单中添加验证码字段: 在你的表单类中导入`CaptchaField`,并将其作为一个字段添加到表单中。例如: ```python from captcha.fields import CaptchaField class MyForm(forms.Form): # 其他字段... captcha = CaptchaField() ``` 5. 在视图函数中验证验证码: 在你的视图函数中,可以通过调用`form.is_valid()`来验证验证码是否正确。例如: ```python def my_view(request): if request.method == 'POST': form = MyForm(request.POST) if form.is_valid(): # 验证码正确,执行相应的逻辑 # ... else: # 验证码错误,处理错误信息 # ... else: form = MyForm() return render(request, 'my_template.html', {'form': form}) ``` 6. 在模板中显示验证码输入框: 在你的模板文件中,可以通过`form.captcha`来渲染验证码输入框。例如: ```html <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">提交</button> </form> ``` 这样,你就可以在Django使用django-simple-captcha生成验证码了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值