一.背景

  在之前实现过django的图片验证码,有自己实现过的,也有基于django-simple-captcha的,都是基于form表单验证,若自己实现,可以获取相应的标签name便可以获取判断,若使用django-simple-captcha只需相应配置即可。但在前后端分离的情况下,就有点摸不着头脑了,序列化时CaptchaField不管作用,百度搜索也没找到相应的办法,于是心想只有重写restframework_jwt自带的登录验证接口及注册接口,都得新增字段。

二.django-simple-captcha简单介绍

  Django Simple Captcha是一个非常简单但高度可定制的Django应用程序,可以将captcha图像添加到任何Django表单中。

  网址如下:https://django-simple-captcha.readthedocs.io/en/latest/,只需按照文档简单配置即可,该插件会对应生成一张表,存放验证码信息及过期时间等。

三.基于django-simple-captcha的drf图片验证码

  1.生成图片验证码接口(我这里将图片转换成了base64),也可以是图片或地址:

from django.http import HttpResponse
from captcha.views import CaptchaStore, captcha_image
import base64
.......
class ImageView(APIView):def get(self, request):hashkey = CaptchaStore.generate_key()try:#获取图片idid_ = CaptchaStore.objects.filter(hashkey=hashkey).first().idimgage = captcha_image(request, hashkey)#将图片转换为base64image_base = base64.b64encode(imgage.content)json_data = json.dumps({"id": id_, "image_base": image_base.decode('utf-8')})except:json_data = Nonereturn HttpResponse(json_data, content_type="application/json")                

  2.注册时的图片验证码:

    2.1序列化:

    这里把图片验证码的id和用户输入的内容都传过来,不易错误,captcha生成的表中的字段expiration是生成图片的时间加五分钟,因此captcha判断的也就是这个过期时间,重写也可以判断这个时间,若当前时间大于它则过期(有效时间五分钟)。

class UserRegSerializer(serializers.ModelSerializer):""""用户注册序列化"""username = serializers.CharField(min_length=2, max_length=20,error_messages={"max_length": "用户名长度应小于等于20","min_length": "用户名长度应大于等于2"},validators=[UniqueValidator(queryset=User.objects.all(), message='用户名已经被使用')],help_text="用户名")code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, label='验证码',error_messages={"blank": "请输入邮箱验证码","required": "邮箱验证码不能为空","max_length": "邮箱验证码格式错误","min_length": "邮箱验证码格式错误"}, help_text='邮箱验证码')email = serializers.CharField(required=True, allow_blank=False,validators=[UniqueValidator(queryset=User.objects.all(), message='用户已经存在')],help_text="邮箱")password = serializers.CharField(style={"input_type": "password"}, write_only=True,help_text="密码")captcha = serializers.CharField(min_length=4, max_length=4, required=True,error_messages={"max_length": "图片验证码格式错误","min_length": "图片验证码格式错误","required": "请输入图片验证码"},help_text="图片验证吗")ima_id = serializers.CharField(required=True, write_only=True, allow_blank=False,help_text="图片验证码id")def validate_code(self, code):verify_codes = EmailVeriyRecord.objects.filter(email=self.initial_data['email']).order_by('-send_time')if verify_codes:last_verfycode = verify_codes[0]five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)if five_minute_ago > last_verfycode.send_time:raise serializers.ValidationError('验证码过期')if code != last_verfycode.code:raise serializers.ValidationError('验证码错误')else:raise serializers.ValidationError('验证码错误')def validate_password(self, password):"""密码长度大于6小于12"""if re.match(REGEX_PWD, password):passelse:raise serializers.ValidationError("密码必须包含数字,字母,特殊符中两到三种,且长度在6-12之间")return passworddef validate_captcha(self, captcha):try:captcha = captcha.lower()except:raise serializers.ValidationError("图片验证码错误")image_code = CaptchaStore.objects.filter(id=self.initial_data['ima_id']).first()if image_code and datetime.now() > image_code.expiration:raise serializers.ValidationError('图片验证码过期')else:if image_code and image_code.response == captcha:passelse:raise serializers.ValidationError("图片验证码错误")# 作用于所有字段def validate(self, attrs):if attrs['username']:passelse:attrs['username'] = attrs['email']del attrs["code"]del attrs["ima_id"]del attrs["captcha"]return attrsclass Meta:model = Userfields = ('email', 'code', 'password', 'username', 'captcha', 'ima_id')

    2.2注册view实现:

class UserRegisterViewset(mixins.CreateModelMixin, mixins.UpdateModelMixin,mixins.RetrieveModelMixin, viewsets.GenericViewSet):"""用户注册接口create:用户添加"""serializer_class = UserRegSerializerqueryset = User.objects.all()authentication_classes = (JSONWebTokenAuthentication, authentication.SessionAuthentication)def create(self, request, *args, **kwargs):serializer = self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)user = self.perform_create(serializer)re_dict = serializer.datapayload = jwt_payload_handler(user)re_dict['token'] = jwt_encode_handler(payload)headers = self.get_success_headers(serializer.data)return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)def get_serializer_class(self):'''重载GenericAPIView中的get_serializer_class函数,调用不同的序列化类,如果是create,就调用UserRegSerializer序列化,否则UserDetailSerializer序列化:return: '''if self.action == 'retrieve':return UserDetailSerializerelif self.action == 'create':return UserRegSerializerreturn UserDetailSerializerdef get_permissions(self):'''重载APIview中的get_perimissions函数,如果是新增用户则不用登录,否则必须登录:return: '''if self.action == 'retrieve':return [permissions.IsAuthenticated()]elif self.action == 'create':return []return []def get_object(self):'''返回当前用户:return: '''return self.request.userdef perform_create(self, serializer):return serializer.save()

  2.登录:

    2.1序列化:

from rest_framework_jwt.settings import api_settingsjwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from django.contrib.auth import authenticate
from rest_framework_jwt.compat import PasswordFieldclass MyloginSerializer(JSONWebTokenSerializer):"""从写登录序列化"""def __init__(self, *args, **kwargs):"""Dynamically add the USERNAME_FIELD to self.fields."""super(JSONWebTokenSerializer, self).__init__(*args, **kwargs)self.fields[self.username_field] = serializers.CharField()self.fields['password'] = PasswordField(write_only=True)self.fields['captcha'] = serializers.CharField(min_length=4, max_length=4, required=True,error_messages={"max_length": "图片验证码格式错误","min_length": "图片验证码格式错误","required": "请输入图片验证码"})self.fields['ima_id'] = serializers.CharField(required=True, allow_blank=False)def validate_captcha(self, captcha):image_code = CaptchaStore.objects.filter(id=self.initial_data['ima_id']).first()five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0)if image_code and five_minute_ago > image_code.expiration:raise serializers.ValidationError('验证码过期')else:if image_code and (image_code.response == captcha or image_code.challenge == captcha):passelse:raise serializers.ValidationError("图片验证码错误")def validate(self, attrs):del attrs["ima_id"]del attrs["captcha"]credentials = {self.username_field: attrs.get(self.username_field),'password': attrs.get('password')}if all(credentials.values()):user = authenticate(**credentials)if user:if not user.is_active:msg = _('User account is disabled.')raise serializers.ValidationError(msg)payload = jwt_payload_handler(user)return {'token': jwt_encode_handler(payload),'user': user}else:msg = _('Unable to log in with provided credentials.')raise serializers.ValidationError(msg)else:msg = _('Must include "{username_field}" and "password".')msg = msg.format(username_field=self.username_field)raise serializers.ValidationError(msg)

    2.2view:

from rest_framework_jwt.views import JSONWebTokenAPIView
from .serializers import MyloginSerializerclass MyJSONWebToken(JSONWebTokenAPIView):""""重写jwt的登录验证,含图片验证码"""serializer_class = MyloginSerializer

  3.url中相应配置:

    url(r'images/$',ImageView.as_view()),url(r'login/$',MyJSONWebToken.as_view(),name="login")

四.总结

  这样做功能是实现了,但感觉有些粗糙,可以把验证码表的数据超过某个时间的自动清除,也可以把数据放入缓存(redis等),希望能提一些改进的建议。

转载于:https://www.cnblogs.com/lyq-biu/p/10077820.html

drf实现图片验证码功能相关推荐

  1. 用Java实现图片验证码功能

    一.什么是图片验证码? 可以参考下面这张图: 我们在一些网站注册的时候,经常需要填写以上图片的信息. 1.图片生成实体类: 1 package com.hexianwei.graphic; 2 3 i ...

  2. canvas——实现图片验证码(功能实现)

    canvas实现图片验证码--效果图如下: 1.html部分代码 <div class="wrapper"><div class="inputBox&q ...

  3. 后台图片验证码功能是什么实现的

    一.导包,1)check_code.py文件:2)Monaco.ttf字体: 二.通过session机制,来实现此功能,部分代码如下: 1 f = BytesIO() 2 img, code = cr ...

  4. javaWeb实现图片验证码功能

    java程序实现画图 public static void main(String[] args)throws Exception {String message="3456789abcde ...

  5. 登录功能图片验证码的实现

    首先从网上下载一个生成验证码的Servlet: package com.train.controller;import java.awt.Color; import java.awt.Font; im ...

  6. Spring Boot整合Shiro + JSP教程(用户认证,权限管理,图片验证码)

    在此首先感谢**编程不良人**up主提供的视频教程 代码都是跟着up的视频敲的,遇到的一些问题也是通过CSDN博主提供的教程解决的,在此也感谢那些提供bug解决方案的前辈们~ 项目完整代码已经发布到g ...

  7. 点击图片验证码更换验证码图片

    做登录注册等功能的时候一般都有图片验证码功能,点击看不清,换一张的时候更换一张验证码,但是又不想整个页面跟着刷新,只刷新一个验证码,因为我的项目是react项目,所以就直接上react的代码了,原理就 ...

  8. SSM框架下实现验证码图片验证功能(源码)

    SSM框架下实现验证码图片验证功能 背景图片资源路径 https://download.csdn.net/download/hero_qhz/10322064 一.首先,在pom里面加上需要用的资源j ...

  9. Day239.RBAC模式、动态加载用户权限资源规则数据规则、【记住我】注销多次登录图片验证码session验证码验证功能 -springsecurity-jwt-oauth2

    1.RBAC权限管理模型 一.RBAC权限模型简介 RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制.模型中有几个关键的术语: 用户:系统接口及功能访问的操 ...

最新文章

  1. 学习使用markdown(markdown篇)
  2. 【数据竞赛】竞赛宝典黑科技:基于开源结果的高端融合策略
  3. 小程序获取openid保存缓存吗_微信小程序把openid放到缓存里
  4. 【数据结构与算法】之深入解析“灯泡开关”的求解思路与算法示例
  5. linux中将光标与操作系统,linux操作系统基本命令介绍(2)
  6. Sublime Text 使用介绍、全套快捷键及插件推荐
  7. Atitit.兼具兼容性和扩展性的配置方案attilax总结
  8. 安卓原生系统_小米新机曝光,运行原生安卓系统;准!四川宜宾5.3级地震提前14秒预警...
  9. 利用U盘装CentOS6.4和将CentOS6.4安装到U盘
  10. 视频教程-思科CCNP专题系列⑤:路由策略路由-思科认证
  11. 第26章 站在巨人肩膀上——游戏引擎技术导论
  12. 汇编实验——乐曲程序(两只老虎)
  13. CallBack函数调用
  14. 看完微信公众号最新的广告分成方案,只想给32个赞
  15. oracle数据库impdp命令的使用方法
  16. 自媒体全是带节奏的标题党,不是创作者不行,而是用户们想看
  17. 2020年阿贝尔(Abel)奖揭晓,两位概率论大佬横扫数学界最高荣誉
  18. 如何在Cisco Packet Tracer中创建多个路由器虚拟局域网(方法一)
  19. 磺酸基-Cy7 叠氮化物 DIPEA(二异丙基乙基胺)盐,Sulfo-Cy7 azide DIPEA (diisopropylethylamine) salt
  20. 最大9W升压型DCDC多串LED恒流驱动

热门文章

  1. 第六周组会摘要工作计划与分工
  2. 伺服阀放大器|通用型电液伺服阀放大器|伺服阀放大器厂家
  3. 人脸识别之insightface开源代码使用:训练、验证、测试(2)
  4. 怎么将静图变动图?用这个网站就够了
  5. 技术杂谈-再谈软硬SDN(2)
  6. 学大伟业2018-2019学年第二学期《自主招生集训课程》
  7. 台式机安装纯ubuntu系统的操作步骤
  8. (十)打包和项目部署
  9. WEB网页设计前端(前台)开发的常用工具推荐
  10. Excel文件筛选结果