图形验证码
class ImageCodeView(View):
def get(self,request):
uuid=request.GET.get('uuid')
if uuid is None:
return HttpResponseBadRequest('没有传递uuid')
text,image=captcha.generate_captcha()
redis_conn=get_redis_connection('default')
redis_conn.setex('img:%s'%uuid,300,text)
return HttpResponse(image,content_type='image/jpeg')
短信验证码功能实现
实现思路
- 接收参数(查询字符串的形式传递过来)
mobile,image_code,uuid - 参数验证
2.1 验证参数是否齐全
2.2 图片验证码是否存在
连接redis,获取redis中的图片验证码
判断验证码是否存在
如果图片验证码未过期,获取之后就可以删除图片验证码
比对图片验证码 - 生成短信验证码
- 保存短信验证码到redis中
- 发送短信
- 返回响应
发送短信验证码的视图函数代码如下:
class SmsCodeView(View):
def get(self,request):
mobile=request.GET.get('mobile')
image_code=request.GET.get('image_code')
uuid=request.GET.get('uuid')
if not all([mobile,image_code,uuid]):
return JsonResponse({'code':RETCODE.NECESSARYPARAMERR,'errmsg':'缺少必要的参数'})
redis_conn=get_redis_connection('default')
redis_image_code=redis_conn.get('img:%s'%uuid)
if redis_image_code==None:
return JsonResponse({'code':RETCODE.NECESSARYPARAMERR,'errmsg':'图片验证码已过期'})
try:
redis_conn.delete('img:%s'%uuid)
except Exception as e:
print(e)
if redis_image_code.decode().lower()!=image_code.lower():
return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '图片验证码错误'})
sms_code='%06d'%randint(0,999999)
redis_conn.setex('sms:%s'%mobile,300,sms_code)
CCP().send_template_sms(mobile,[sms_code,5],1)
return JsonResponse({'code':RETCODE.OK,'errmsg':'短信验证码发送成功'})
注册功能实现
实现思路:
- 接收数据
- 验证数据
2.1 参数是否齐全
2.2 手机号的格式是否齐全
2.3 密码是否符合格式
2.4 密码和确认密码是否一致
2.5 短信验证码是否和redis一致 - 保存注册信息
- 返回响应跳转到指定页面
完整代码:
def post(self,request):
mobile=request.POST.get('mobile')
password = request.POST.get('password')
password2 = request.POST.get('password2')
smscode = request.POST.get('sms_code')
if not all([mobile,password,password2,smscode]):
return HttpResponseBadRequest('缺少必要的参数')
if not re.match(r'^1[3-9]\d{9}$',mobile):
return HttpResponseBadRequest('手机号不符合规则')
if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
return HttpResponseBadRequest('请输入8—20位数字和字母的组合')
if password!=password2:
return HttpResponseBadRequest('两次密码不一致')
redis_conn=get_redis_connection('default')
redis_sms_code=redis_conn.get('sms:%s'%mobile)
if redis_sms_code is None:
return HttpResponseBadRequest('短信验证码已过期')
elif smscode!=redis_sms_code.decode(): #从redis数据库导出的数据需要解码
return HttpResponseBadRequest('短信验证码错误')
#create_user()可以使用系统的方法来对密码进行加密
try:
user=User.objects.create_user(username=mobile,
mobile=mobile,
password=password)
except Exception as e:
return HttpResponseBadRequest('注册失败')
return HttpResponse('注册成功')
注意:
- 正则表达
导入re库,re.match(正则表达式,待匹配字符串)可以匹配单个或多个字符串
单字符匹配:
匹配多个字符:
- User类
User类继承于AbstractUser,因此不需要定义username,password这些
create_user()可以使用系统的方法来对密码进行加密 - 从redis数据库导出的数据需要解码
首页展示
- 新建home应用
- 注册试图函数重定向至首页
保持状态
- login方法
django用户认证系统提供了login方法(from django.contrib.auth import login)
状态保持:将通过认证的用户的唯一标识信息写入到当前session会话中
使用:login(request,user) - 设置cookie
代码:
response= redirect(reverse('home:index'))
response.set_cookie('is_login',True)
response.set_cookie('username',user.username,max_age=7*24*3600)
return response
登录实现
实现思路:
- 获取参数
mobile,password,remember - 参数验证
2.1 验证手机号是否符合规则
2.2 验证密码是否符合规则 - 用户认证登录
采用系统自带的认证方法进行认证:如果我们的用户名和密码正确,会返回user;如果用户名和密码不正确,会返回None
from django.contrib.auth import authenticate
由于当前判断信息是手机号,所以需要修改一下认证字段 - 状态保持
- 根据用户选择是否记住登录状态来进行判断
- 为了首页显示需要设置一些cookie信息
- 返回响应
完整代码:
class LoginView(View):
def get(self,request):
return render(request,'login.html')
def post(self, request):
mobile = request.POST.get('mobile')
password = request.POST.get('password')
remember=request.POST.get('remember')
from django.contrib.auth import authenticate
user = authenticate(mobile=mobile,password=password)
if user is None:
return HttpResponseBadRequest('用户名或密码不正确')
from django.contrib.auth import login
login(request, user)
response = redirect(reverse('home:index'))
if remember!='on':
#浏览器关闭之后,不记录登录信息
request.session.set_expiry(0)
response.set_cookie('is_login', True)
response.set_cookie('username', user.username, max_age=14 * 24 * 3600)
else:
#默认记录两周
request.session.set_expiry(None)
response.set_cookie('is_login', True,max_age=14*24*3600)
response.set_cookie('username', user.username, max_age=14 * 24 * 3600)
return response
退出登录
实现思路:
- session数据清除
logout():清理session会话信息 - 删除部分cookie数据
delete_cookie() - 跳转到首页
完整代码:
from django.contrib.auth import logout
class LogoutView(View):
def get(self,request):
logout(request)
response=redirect(reverse('home:index'))
response.delete_cookie('is_login')
return response
忘记密码
实现思路:
- 接收数据
- 验证数据
2.1 判断参数是否齐全
2.2 手机号是否符合规则
2.3 判断密码是否符合规则
2.4 判断确认密码是否和密码一致
2.5 判断短信验证码是否正确 - 根据手机号进行用户信息查询
- 如果手机号查询出用户信息则进行用户密码的修改
- 如果手机号没有查询出用户信息,则进行新用户的创建
- 进行页面跳转,跳转到登录页面
- 返回响应
完整代码:
class ForgetPasswordView(View):
def get(self,request):
return render(request,'forget_password.html')
def post(self,request):
mobile=request.POST.get('mobile')
password=request.POST.get('password')
password2=request.POST.get('password2')
smscode=request.POST.get('sms_code')
if not all([mobile,password,password2,smscode]):
return HttpResponseBadRequest('参数不全')
if not re.match(r'^1[3-9]\d{9}$',mobile):
return HttpResponseBadRequest('手机号不正确')
if not re.match(r'^[0-9a-zA-Z]{8,20}$',password):
return HttpResponseBadRequest('密码格式不正确')
if password!=password2:
return HttpResponseBadRequest('密码不一致')
redis_conn=get_redis_connection('default')
redis_sms_code=redis_conn.get('sms:%s'%mobile)
if redis_sms_code is None:
return HttpResponseBadRequest('短信验证码已过期')
if redis_sms_code.decode()!=smscode:
return HttpResponseBadRequest('短信验证码错误')
try:
user=User.objects.get(mobile=mobile)
except Exception:
try:
User.objects.create_user(username=mobile,
mobile=mobile,
password=password)
except Exception:
return HttpResponseBadRequest('修改失败,请稍后再试')
else:
user.set_password(password)
user.save()
return redirect(reverse('users:login'))