Django验证码实现与登录验证码展示策略
May 14 2016Django实现验证码有很多现成可用的库,Google后选择Django Simple Captcha,需要做一些展示与表单验证方面的定制。
验证码展示
默认的验证码展示形式不是很适合我们网站的样式,所以在settings中做了一些定制。
# 验证码设置
CAPTCHA_FOREGROUND_COLOR = '#d83a46' # 验证码字体颜色
CAPTCHA_BACKGROUND_COLOR = '#f5f5f5' # 验证码背景颜色
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',) # 验证码混淆配置,这里设置的点点
CAPTCHA_CHALLENGE_FUNCT = 'random_char_challenge' # 验证码生成函数配置
为了提供验证码的识别率,定制了一个随机字符串生成函数来生成验证码。
# coding: utf-8
import random
from captcha.conf import settings
from six import u
def random_char_challenge():
chars, ret = u('acefghkprtuvwxy34679'), u('')
for i in range(settings.CAPTCHA_LENGTH):
ret += random.choice(chars)
return ret.upper(), ret
表单验证
Django Simple Captcha提供了from captcha.fields import CaptchaField
用来做验证,但是这个field相对来说说是不可见的,其实参数是提供了验证码与hashkey两个,所以自己按照它Model的逻辑写了一个验证表单。
# coding: utf-8
import logging
from datetime import datetime
from django import forms
from django.conf import settings
from captcha.models import CaptchaStore
class CaptchaForm(forms.Form):
'''
验证码验证Form
'''
hashkey = forms.CharField(label='图片验证码的key值')
captcha = forms.CharField(label='图片验证码')
def clean_hashkey(self):
'''
验证码key值
'''
hashkey = self.cleaned_data.get('hashkey')
length = len(hashkey)
if length < 4 or length > 40:
raise forms.ValidationError('hashkey长度错误')
return hashkey
def clean_captcha(self):
'''
验证验证码正确
'''
hashkey = self.cleaned_data.get('hashkey')
captcha = self.cleaned_data.get('captcha')
length = len(captcha)
if length < 4 or length > 6:
raise forms.ValidationError('验证码长度错误')
cs = CaptchaStore.objects.filter(response=captcha.lower(), hashkey=hashkey).first()
if not cs or cs.expiration < datetime.now():
raise forms.ValidationError('验证码错误')
return captcha
登录验证码显示策略
刚开始做登录的时候,每次登录都必须填写验证码,产品同事表示用户体验不是很好,要求首次登录不需要显示验证码,输入密码错误后才显示。这里涉及到一个判断逻辑。
- 用户登录,提交用户名/密码,在redis中取用户输入密码错误次数
- 如果次数超过1则验证是否提交验证码,否则直接验证用户名密码
- 判断如果用户的密码提交错误redis计数+1,并更新过期时间为10分钟
- 如果用户正常登录则删除用户保存在redis中的数