前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >django-simple-captcha 图形验证码使用总结

django-simple-captcha 图形验证码使用总结

作者头像
卓越笔记
发布2023-02-18 11:38:41
1.1K0
发布2023-02-18 11:38:41
举报
文章被收录于专栏:卓越笔记

官方文档

基本配置

安装 captcha

pip install  django-simple-captcha

settings.py

代码语言:javascript
复制
# 添加 captcha APP
INSTALLED_APPS = [
     # 添加 验证码 APP
    'captcha',

]

# Captcha 配置
# Captcha 默认格式
CAPTCHA_OUTPUT_FORMAT = '%(image)s %(text_field)s %(hidden_field)s '
CAPTCHA_NOISE_FUNCTIONS = (
    # 'captcha.helpers.noise_null',  # 没有样式
    # 'captcha.helpers.noise_arcs',  # 线
    'captcha.helpers.noise_dots',  # 点
)
# 图片中的文字为随机英文字母,如 mdsh
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.random_char_challenge'
# 图片中的文字为数字表达式,如 2 + 2 =
# CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
# 超时(minutes)
CAPTCHA_TIMEOUT = 30
# 验证码输入框指定 TEMPLATE, 表单使用 CaptchaField 字段生效
CAPTCHA_TEXT_FIELD_TEMPLATE = "captcha_text_field.html"

自定义 CAPTCHA_TEXT_FIELD TEMPLATE

captcha_text_field.html(加了一个 placeholder)

代码语言:javascript
复制
<input autocapitalize="off" autocomplete="off" autocorrect="off" spellcheck="false" id="{{id}}_1" name="{{name}}_1" type="text" placeholder="请输入验证码" />

项目 urls.py

代码语言:javascript
复制
urlpatterns = [
               # 添加 captcha url
               url(r'^captcha/', include('captcha.urls')),  # django 1.11
              ]

官方用法

Adding to a Form

Using a CaptchaField is quite straight-forward:

Define the Form

To embed a CAPTCHA in your forms, simply add a CaptchaField to the form definition:

代码语言:javascript
复制
from django import forms
from captcha.fields import CaptchaField

class CaptchaTestForm(forms.Form):
    myfield = AnyOtherField()
    captcha = CaptchaField()

…or, as a ModelForm:

代码语言:javascript
复制
from django import forms
from captcha.fields import CaptchaField

class CaptchaTestModelForm(forms.ModelForm):
    captcha = CaptchaField()
    class Meta:
        model = MyModel

Validate the Form

In your view, validate the form as usual. If the user didn’t provide a valid response to the CAPTCHA challenge, the form will raise a ValidationError:

代码语言:javascript
复制
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_to_response('template.html',locals())

Use to Template

代码语言:javascript
复制
{{ form.captcha }}

Passing arguments to the field

CaptchaField takes a few optional arguements:

  • output_format will let you format the layout of the rendered field. Defaults to the value defined in : CAPTCHA_OUTPUT_FORMAT.
  • id_prefix Optional prefix that will be added to the ID attribute in the generated fields and labels, to be used when e.g. several Captcha fields are being displayed on a same page. (added in version 0.4.4)
  • generator Optional callable or module path to callable that will be used to generate the challenge and the response, e.g. generator='path.to.generator_function' or generator=lambda: ('LOL', 'LOL'), see also Generators and modifiers. Defaults to whatever is defined in settings.CAPTCHA_CHALLENGE_FUNCT.

Example usage for ajax form

An example CAPTCHA validation in AJAX:

代码语言:javascript
复制
from django.views.generic.edit import CreateView
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url
from django.http import HttpResponse
import json

class AjaxExampleForm(CreateView):
    template_name = ''
    form_class = AjaxForm

    def form_invalid(self, form):
        if self.request.is_ajax():
            to_json_response = dict()
            to_json_response['status'] = 0
            to_json_response['form_errors'] = form.errors

            to_json_response['new_cptch_key'] = CaptchaStore.generate_key()
            to_json_response['new_cptch_image'] = captcha_image_url(to_json_response['new_cptch_key'])

            return HttpResponse(json.dumps(to_json_response), content_type='application/json')

    def form_valid(self, form):
        form.save()
        if self.request.is_ajax():
            to_json_response = dict()
            to_json_response['status'] = 1

            to_json_response['new_cptch_key'] = CaptchaStore.generate_key()
            to_json_response['new_cptch_image'] = captcha_image_url(to_json_response['new_cptch_key'])

            return HttpResponse(json.dumps(to_json_response), content_type='application/json')

And in javascript your must update the image and hidden input in form

Example usage ajax refresh button

# html:

代码语言:javascript
复制
<form action='.' method='POST'>
    {{ form }}
    <input type="submit" />
    <button class='js-captcha-refresh'></button>
</form>

# javascript:

代码语言:javascript
复制
$('.js-captcha-refresh').click(function(){
    $form = $(this).parents('form');

    $.getJSON($(this).data('url'), {}, function(json) {
        // This should update your captcha image src and captcha hidden input
    });

    return false;
});

Example usage ajax refresh

# javascript:

代码语言:javascript
复制
$('.captcha').click(function () {
    $.getJSON("/captcha/refresh/", function (result) {
        $('.captcha').attr('src', result['image_url']);
        $('#id_captcha_0').val(result['key'])
    });


});

个人用法

个人使用时未使用到 Django 的表单的验证,直接在前端用 ajax 获取验证码,加了 1 分钟缓存,即 1 分钟只能获取一次,除非使用掉。

view 里调用生成验证码的代码

代码语言:javascript
复制
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url

from ipware.ip import get_ip

def view_test(request):
	# hashkey 验证码生成的秘钥,image_url 验证码的图片地址
	hashkey_name = "hashkey_%s" % get_ip(request)
	hashkey = cache.get(hashkey_name)
	if not hashkey:
	    hashkey= CaptchaStore.generate_key()
	    cache.set(hashkey_name, hashkey, 60 * 1)
	image_url = captcha_image_url(hashkey)

	return ""  # 此处省略

改造后的 captcha/views.py 的 captcha_refresh 函数,加入了 1 分钟缓存

代码语言:javascript
复制
def captcha_refresh(request):
    """  Return json with new captcha for ajax refresh request """
    ip = get_ip(request)
    if not request.is_ajax():
        raise Http404

    if cache.get("hashkey_%s" % ip):
        to_json_response = {
            'code': 403,
            'msg': "1 分钟内只能获取 1 次验证码"
        }
        return HttpResponse(json.dumps(to_json_response), content_type='application/json')

    new_key = CaptchaStore.pick(ip=ip)
    cache.set("hashkey_%s" % ip, new_key, 60 * 1)  # 1 分钟获取 1 次
    to_json_response = {
        'code': 200,
        'key': new_key,
        'image_url': captcha_image_url(new_key),
        'audio_url': captcha_audio_url(new_key) if settings.CAPTCHA_FLITE_PATH else None
    }
    return HttpResponse(json.dumps(to_json_response), content_type='application/json')

前端代码,获取验证码图片

代码语言:javascript
复制
<div class="m-form-group am-u-sm-6 blog-clear-right">
    <div class="am-input-group">
        <input autocomplete="off" id="id_captcha_1" name="captcha_code" type="text"
               placeholder="* 验证码" class="am-form-field" required="required">
        <span class="am-input-group-btn">
            <img src="{{ image_url }}" alt="captcha" class="captcha" id="captcha"
                 style="height: 38px;">
        </span>

        <input id="id_reg_captcha_0" name="captcha_hashkey" type="hidden" value="{{ hashkey }}">
    </div>
    <script>
        $('#captcha').click(function () {
            $.getJSON("/captcha/refresh/", function (result) {
                if (result['code'] === 200) {
                    $('#captcha').attr('src', result['image_url']);
                    $('#id_reg_captcha_0').val(result['key'])
                } else {
                    toastr.warning(result['msg']);
                }
            });

        });
    </script>
</div>

view 里验证验证码是否有效,有效则在数据库表里 删除该条数据 以及 删除 1 分钟的缓存 key

代码语言:javascript
复制
from captcha.models import CaptchaStore
from captcha.helpers import captcha_image_url

from ipware.ip import get_ip


def view_test_2(request):
	ip = get_ip(request)

	# 前端回传:captcha_code 验证码的值,captcha_hashkey 哈希之后的值
    captcha_code = request.POST.get("captcha_code".strip(), None)
    captcha_hashkey = request.POST.get("captcha_hashkey", None)
    try:
        # 如果没过期找到了就删除掉
        CaptchaStore.objects.get(response=captcha_code.lower(), hashkey=captcha_hashkey,
                                 expiration__gt=timezone.now()).delete()
        if cache.has_key("hashkey_%s" % ip):
            # 验证通过,如果还存在 key, 就删除掉
            cache.delete("hashkey_%s" % ip)

    except CaptchaStore.DoesNotExist:
        return HttpResponse("验证码无效或已过期")

	return ""  # 此处省略

其他用法

https://my.oschina.net/hellotest/blog/1623597

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-9 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 官方文档
  • 基本配置
    • 安装 captcha
      • settings.py
        • 自定义 CAPTCHA_TEXT_FIELD TEMPLATE
          • 项目 urls.py
          • 官方用法
            • Adding to a Form
              • Define the Form
                • Validate the Form
                  • Use to Template
                    • Passing arguments to the field
                      • Example usage for ajax form
                        • Example usage ajax refresh button
                          • Example usage ajax refresh
                          • 个人用法
                            • view 里调用生成验证码的代码
                              • 改造后的 captcha/views.py 的 captcha_refresh 函数,加入了 1 分钟缓存
                                • 前端代码,获取验证码图片
                                  • view 里验证验证码是否有效,有效则在数据库表里 删除该条数据 以及 删除 1 分钟的缓存 key
                                  • 其他用法
                                  相关产品与服务
                                  验证码
                                  腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
                                  领券
                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档