可重用用户注册系统
8、图片验证码
为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能。 在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发(不必重复造轮子)。这个库叫做django-simple-captcha。 具体安装教程 :戳我
Django表单
from captcha.fields import CaptchaField
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(label='用户名', required=True, min_length=4, max_length=128)
password = forms.CharField(label='密码', required=True, min_length=4, max_length=10)
captcha = CaptchaField(label='验证码')
def login(request):
if request.method == "POST":
login_form = LoginForm(request.POST)
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = SiteUser.objects.filter(name=username, password=password).first()
if user:
request.session['is_login'] = True
request.session['user_id'] = user.id
request.session['username'] = user.name
return render(request, 'login/index.html')
else:
message = "用户名或密码错误"
return render(request, 'login/login.html', locals())
else:
message = "填写的信息不正确或是不合法!"
return render(request, 'login/login.html', locals())
login_form = LoginForm()
return render(request, 'login/login.html', locals())
Templatest页面优化
# login/login.html(部分修改)
# 修改1、不同的报错显示不同的信息
<h3 style="text-align: center">用户登录</h3>
{% if login_form.captcha.errors %}
<div class="alert alert-warning" role="alert">
<strong>登陆失败!</strong> 验证码不正确!
</div>
{% elif message %}
<div class="alert alert-warning" role="alert">
<strong>登录失败!</strong> {{ message }}
</div>
{% endif %}
{% csrf_token %}
<div class="form-group">
<label>{{ login_form.username.label }}</label>
<input type="text" class="form-control" name="username">
</div>
<div class="form-group">
<label>{{ login_form.password.label }}</label>
<input type="password" class="form-control" name="password">
<small class="form-text text-muted">密码必须是由字母、数字或是特殊符号组成</small>
</div>
<div class="form-group">
<label>{{ login_form.captcha.label }}</label>
{{ login_form.captcha }}
</div>
验证是否正确
localhost:8000/login
9、邮箱注册
发送邮件功能测试
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'binghh1314@163.com'
EMAIL_HOST_PASSWORD = 'ZJPCYZRDKCUKIQNS'
EMAIL_USER_SSL = False
163邮箱:设置–>SMTP设置–>开启SMTP的所有服务并复制授权码 确保SMTP开启才能发送使用该邮箱发送邮件 需要的话可以再次新增授权码
python manage.py shell
In [2]: from loginRegister.settings import EMAIL_HOST_USER
In [3]: from django.core.mail import send_mail
In [4]: send_mail("test","content",EMAIL_HOST_USER,['binghh1314@163.c
...: om'])
Out[4]: 1
在163邮箱端查看是否能够接收到邮件
基本的注册功能实现
class RegisterForm(forms.Form):
username = forms.CharField(label='用户名', required=True, max_length=128)
password1 = forms.CharField(label='密码', required=True, max_length=256)
password2 = forms.CharField(label='确认密码', required=True, max_length=256)
email = forms.EmailField(label="邮箱地址")
captcha = CaptchaField(label='验证码')
- 如果用户已经登录,则不能跳转到注册界面
- 如果是GET请求,返回用户注册的HTML页面
- 如果是POST请求,先验证提交的数据是否通过,清洗数据。接下来判断用户名的邮箱是否已经被注册,将注册信息储存到数据库并跳转到登录界面
- 额外功能:为了数据的安全性注册时,密码存储到数据不铭文存储,二十先加密再存储
loginRegister/views.py
def login(request):
if request.method == "POST":
login_form = LoginForm(request.POST)
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = SiteUser.objects.filter(name=username, password=password).first()
if user:
request.session['is_login'] = True
request.session['user_id'] = user.id
request.session['username'] = user.name
return render(request, 'login/index.html')
else:
message = "用户名或密码错误"
return render(request, 'login/login.html', locals())
else:
message = "填写的信息不正确或是不合法!"
return render(request, 'login/login.html', locals())
login_form = LoginForm()
return render(request, 'login/login.html', locals())
templates/login/register.html
{% if register_form.captcha.errors %}
<div class="alert alert-warning" role="alert">
<strong>注册失败!</strong> 验证码不正确!
</div>
{% elif message %}
<div class="alert alert-warning" role="alert">
<strong>注册失败!</strong> {{ message }}
</div>
{% endif %}
<form action="/register/" method="post">
{% csrf_token %}
<div class="form-group">
<label>{{ register_form.username.label }}</label>
<input type="text" class="form-control" name="username">
<small id="emailHelp" class="form-text text-muted"></small>
</div>
<div class="form-group">
<label>{{ register_form.email.label}}</label>
<input type="email" class="form-control" name="email">
</div>
<div class="form-group">
<label>{{ register_form.password1.label }}</label>
<input type="password" class="form-control" name="password1">
<small>密码必须由字母数字特殊字符组成</small>
</div>
<div class="form-group">
<label>{{ register_form.password2.label }}</label>
<input type="password" class="form-control" name="password2">
</div>
<div class="form-group">
<label>{{ register_form.captcha.label }}</label>
{{ register_form.captcha }}
</div>
进入浏览器进行注册
注册添加密码加密功能
对于如何加密密码,有很多不同的途径,其安全程度也高低不等。这里我们使用Python内置的hashlib库,使用哈希值的方式加密密码,可能安全等级不够高,但足够简单,方便使用。
loginRegister/utils.py
import hashlib
def hash_code(s, salt='mysite'):
h = hashlib.sha256()
s += salt
h.updates(s.encode())
return h.hexdigest()
loginRegister/views.py
def login(request):
user = SiteUser.objects.filter(name=username, password=hash_code(password)).first()
def register(request):
new_user = SiteUser(name=username, password=hash_code(password1), email=email)
- 测试查看加密后的密码在数据库中的形态
邮箱注册确认
很自然地,我们会想到如果能用邮件确认的方式对新注册用户进行审查,既安全又正式,也是目前很多站点的做法。
既然要区分通过和未通过邮件确认的用户,那么必须给用户添加一个是否进行过邮件确认的属性 另外,我们要创建一张新表,用于保存用户的确认码以及注册提交的时间。
class SiteUser(models.Model):
has_confirmed = models.BooleanField(default=False)
class ConfirmString(models.Model):
code = models.CharField(max_length=256)
user = models.OneToOneField('SiteUser', on_delete=models.CASCADE)
create_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.name + ": " + self.code
class Meta:
ordering = ["-create_time"]
verbose_name = "确认码"
verbose_name_plural = "确认码"
数据库模型更改一定要注意进行数据库的迁移和写入数据库
同时应当修改admin.py,方便在后台进行修改和观察数据
admin.site.register(ConfirmString)
new_user = SiteUser(name=username, password=hash_code(password1), email=email)
new_user.save()
code = make_confirm_string(new_user)
send_email(email, code)
import datetime
def make_confirm_string(user):
print('确认码生成中.......')
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
code = hash_code(user.name, now)
ConfirmString.objects.create(code=code, user=user, )
return code
def send_email(email, code):
print('邮件发送中......')
subject = '注册确认邮件'
text_content = ''' 感谢注册,这里是登录注册系统网站! \
如果你看到这条消息,说明你的邮箱服务器不提供HTML连接功能,请联系管理员!
'''
html_content = '''
<p>感谢注册<a href="http://{}/confirm/?code={}" target=blank>点击验证</a>. \
这里是登录注册系统网站</p>
<p>请点击站点链接完成注册确认!</p>
<p>此链接有效期为{}天!</p>
'''.format('127.0.0.1:8000', code, settings.CONFIRM_DAYS)
send_mail(subject, text_content,
settings.EMAIL_HOST_USER, email, html_message=html_content)
CONFIRM_DAYS = 3
def register(request):
........
if same_name_user:
message = "该邮箱已经注册过了!"
return render(request, 'login/register.html', locals())
try:
new_user = SiteUser(name=username, password=hash_code(password1), email=email)
new_user.save()
code = make_confirm_string(new_user)
print('code:', code)
send_email(email, code)
message = '邮件已发送!请前往邮箱确认!'
except Exception:
return render(request, 'login/register.html', locals())
else:
return render(request, 'login/login.html', locals())
register_form = RegisterForm()
return render(request, 'login/register.html', locals())
- 测试邮件能否发送成功
注册一个新用户,测试能否收到邮件 - 处理邮件请求
path('confirm/', views.user_confrim),
在视图中添加user_confirm类
- 获取确认码信息
- 数据库中是否有该确认码,如果没有,返回说是无效的请求
- 数据库中是否有该确认码,如果有,判断是否过期?如果过期,删除用户信息
|