最近在做一个好玩的通用django单点登录系统,登录系统少不了验证码,参考了一下别人的做法和开源项目,总结一下。
结果如下:
主要思路流程是,后端根据随机码绘图,然后做混淆(我这里几乎没做模糊之类的混淆),最后将随机验证码写进后端session里,前端获取图像后,提交时与session里的验证码做比较。流程还是比较简单的,大致代码如下。
1.captcha_handle.py
captcha_handle.py #用于生成随机字符串以及生成验证码图片 # -*- coding:utf-8 -*- import random,string from PIL import Image,ImageDraw,ImageFont,ImageFilter #生成随机字符串 def _getRandomChar(): #string模块包含各种字符串,以下为小写字母加数字 ran = string.ascii_lowercase+string.digits char = '' for i in range(4): char += random.choice(ran) return char #返回一个随机的RGB颜色 def _getRandomColor(): return (random.randint(50,150),random.randint(50,150),random.randint(50,150)) def create_captcha(): #创建图片,模式,大小,背景色 img = Image.new('RGB', (120,30), (255,255,255)) #创建画布 draw = ImageDraw.Draw(img) #设置字体 font = ImageFont.truetype('Arial.ttf', 25) code = _getRandomChar() #将生成的字符画在画布上 for t in range(4): draw.text((30*t+5,0),code[t],_getRandomColor(),font) #生成干扰点 for _ in range(random.randint(0,50)): #位置,颜色 draw.point((random.randint(0, 120), random.randint(0, 30)),fill=_getRandomColor()) #使用模糊滤镜使图片模糊 # img = img.filter(ImageFilter.BLUR) #保存 #img.save(''.join(code)+'.jpg','jpeg') return img,code if __name__ == '__main__': create_code()
2.views.py
views.py #视图,生成验证码图片和code,返回图片,code存进session class get_captcha(View): def get(self, request): ''' 生成验证码图片和验证码code,返回验证码图片,并以形式将验证码存放在session里 ''' try: f = BytesIO() img, code = create_captcha() request.session["captcha"] = code img.save(f,'PNG') return HttpResponse(f.getvalue()) except Exception as e: log().error(str(e))
3.login.html
{# html #} <div class="col-xs-4"> <img id="captcha_img" src="{% url 'get_captcha' %}" onclick="refresh_captcha()" style="margin-top: 28px;"> <p class="help-block" onclick="refresh_captcha()"> 看不清楚?换一张! </p> </div> {# js #} <script> //刷新验证码 function refresh_captcha() { $("#captcha_img").attr("src",$("#captcha_img")[0].src + '?'); }; </script>
4.url.py
url(r'^get_captcha/$',cas_views.get_captcha.as_view(), name="get_captcha"),
5.views.py
#校验验证码是否正确 if request.session["captcha"].lower() != captcha.lower(): return JsonResponse({"status":False, "msg":"验证码错误!"})
一些代码是参考网络上其他开源代码,不过其实也挺简单的,熟悉request.session就差不多了。做个记录。