验证码
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')