Captcha验证码

验证码

URL

url(r'^captcha/$', views.CaptchaView.as_view(), name=u'captcha'), # 验证码
url(r'^login/$', views.UserLoginView.as_view(), name='login'), # 登录

View

from DjangoCaptcha import Captcha

class CaptchaView(DjangoView):
    def get(self, request, *args, **kwargs):
        captcha = Captcha(request)
        captcha.img_width = 100
        captcha.img_height = 40
        captcha.type = 'word'
        captcha.words = [''.join(random.sample(string.digits, 4))]
        return captcha.display()
    
    
class UserLoginView(generics.GenericAPIView):
    """UserLoginView:
    用户登录
    """
    serializer_class = LoginSerializer
    permission_classes = (IsNotAuthenticated, )

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        response = Response({"detail":"登录成功"})
        return response

Serializer

from DjangoCaptcha import Captcha

class LoginSerializer(serializers.Serializer):
    username = serializers.CharField(label="用户名",write_only=True)
    password = PasswordField()
    code = serializers.IntegerField(label="验证码",write_only=True)

    def validate_code(self, code):
        if settings.DEBUG and code == 666:
            return code

        ca = Captcha(self.context['request'])
        if not ca.check(str(code)):
            raise serializers.ValidationError(u'验证码错误')
        return code

    def validate(self, data):
        try:
            user = User.objects.get(username=data['username'])
            if user.check_password(data['password']):
                login(self.context['request'], user)
                UserLog.add_log(user, "登录")
            else:
                raise serializers.ValidationError(u'用户名或密码错误')
        except User.DoesNotExist:
            raise serializers.ValidationError(u'用户名或密码错误')
        return data

验证码(low逼版本)

def get_valid_img(request):
    # 获取随机颜色的函数
    def get_random_color():
        return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)

    # 生成一个图片对象
    img_obj = Image.new(
        'RGB',
        (220, 35),
        get_random_color()
    )
    # 在生成的图片上写字符
    # 生成一个图片画笔对象
    draw_obj = ImageDraw.Draw(img_obj)
    # 加载字体文件, 得到一个字体对象
    font_obj = ImageFont.truetype("static/font/kumo.ttf", 28)
    # 开始生成随机字符串并且写到图片上
    tmp_list = []
    for i in range(2):
        # u = chr(random.randint(65, 90))  # 生成大写字母
        # l = chr(random.randint(97, 122))  # 生成小写字母
        n = str(random.randint(0, 9))  # 生成数字,注意要转换成字符串类型

        tmp = random.choice([n])
        tmp_list.append(tmp)
        draw_obj.text((20 + 80 * i, 0), tmp, fill=get_random_color(), font=font_obj)

        # draw_obj.text((40 + 40 * i, 0), '+', fill=get_random_color(), font=font_obj)
    # oper_list = ['+', '=']
    # draw_obj.text((20 + 40, 0), oper_list[0], fill=get_random_color(), font=font_obj)
    # draw_obj.text((20 + 120, 0), oper_list[1], fill=get_random_color(), font=font_obj)

    # 保存到session
    request.session["valid_code"] = "".join(tmp_list)
    # 加干扰线
    width = 220  # 图片宽度(防止越界)
    height = 35
    for i in range(5):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw_obj.line((x1, y1, x2, y2), fill=get_random_color())

    # 加干扰点
    for i in range(40):
        draw_obj.point((random.randint(0, width), random.randint(0, height)), fill=get_random_color())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw_obj.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())

    # 不需要在硬盘上保存文件,直接在内存中加载就可以
    io_obj = BytesIO()
    # 将生成的图片数据保存在io对象中
    img_obj.save(io_obj, "png")
    # 从io对象里面取上一步保存的数据
    data = io_obj.getvalue()

    return HttpResponse(data, content_type='image/png')
posted @ 2019-07-06 15:47  久末丶  阅读(1072)  评论(0编辑  收藏  举报