1. 验证码生成
2. 登录表单forms.py
class LoginForm(FlaskForm):
name = StringField(
# 指的是表单前面的内容;
label="用户名",
validators=[
DataRequired("请输入用户名!"),
Length(3, 20),
],
render_kw={
'placeholder': "请输入用户名",
"class": "form-control"
}
)
pwd = PasswordField(
label="密码",
validators=[
DataRequired("请输入密码!")
],
render_kw={
'placeholder': "请输入密码",
"class": "form-control"
}
)
verify_code = StringField(
label="验证码",
validators=[
DataRequired(),
]
)
submit = SubmitField(
render_kw={
'value': "登录",
'class': 'btn btn-success pull-right'
}
)
3. 视图函数
- 向html页面响应验证码图片
# 将验证码图片传给前端;
@app.route('/code/')
def get_code():
# 1. 生成验证码;
from doc.get_code import gene_code
image, code = gene_code()
# 2. 将验证码图片以二进制的方式写在内存中
buf = BytesIO()
image.save(buf, 'png')
buf_str = buf.getvalue()
# 3. 将数据响应给前端页面
response = make_response(buf_str)
response.headers['Content-Type'] = 'image/png'
# 将验证码内容写入session会话中;
session['code'] = code
print(code)
return response
- 用户登录处理
@app.route('/login/', methods=['POST', 'GET'])
def login():
# 实例化定义的登录表单;
form = LoginForm()
# 判断用户的HTTP请求方法
if request.method == 'POST':
# 1). 接收提交的数据;
data = form.data
name = data['name']
pwd = data['pwd']
code = data['verify_code']
# 2). 判断用户名是否存在, 密码是否正确?
u = User.query.filter_by(name=name).first()
if u and check_password_hash(u.pwd, pwd):
if code == session['code']:
session['user'] = u.name
session['user_id'] = u.id
userlog = UserLog(
user_id=u.id,
ip=request.remote_addr,
area=get_ip_area(request.remote_addr)
)
db.session.add(userlog)
db.session.commit()
return '登录成功'
else:
flash("验证码错误", 'error')
return redirect('/login/')
else:
# flash: 消息闪现,
# 如何在前端html页面显示? Jinja2 get_flash_messages()
# 返回的是一个列表, 想依次显示内容, 需要用到for循环;
flash('用户或者密码不正确!')
return redirect(url_for('login'))
else:
return render_template('login.html', form=form)
- 用户登出
@app.route('/logout/')
def logout():
# 将会话中的key值弹出;
session.pop('user', None)
session.pop('user_id', None)
# 注销跳转到登录页面, 或者公共首页
return redirect(url_for('login'))
3. 登录页面(templates/login.html)
{% extends 'base.html' %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block content %}
<div class="col-md-8 col-md-offset-2">
{# 显示闪现的所有信息 #}
{% for msg in get_flashed_messages(category_filter='ok') %}
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<strong>Success!</strong> {{ msg }}.
</div>
{% endfor %}
{% for msg in get_flashed_messages(category_filter='error') %}
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span>
</button>
<strong>Warning!</strong> {{ msg }}.
</div>
{% endfor %}
{{ wtf.quick_form(form) }}
<img src="/code/" onclick="this.src='/code/'">
</div>
{% endblock %}
4. 效果展示
获取验证码
登录界面效果