前端
模板文件
base.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static',filename='/bootstrap/bootstrap.4.6.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static',filename='/css/init.css') }}">
{% block head %}{% endblock %}
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="#">菜鸡学安全</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">首页 <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">发布问答</a>
</li>
<li class="nav-item ml-2">
<form class="form-inline my-2 my-lg-0" method="GET" action="#">
<input class="form-control mr-sm-2" type="search" placeholder="关键字" aria-label="Search" name="q">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
</form>
</li>
</ul>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="#">登录</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">注册</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
{% block body %}{% endblock %}
</div>
</body>
</html>
登录页面前端
{% extends "base.html" %}
{% block title %}
菜鸡学安全
{% endblock %}
{% block head %}{% endblock %}
{% block body %}
<div class="row mt-4">
<div class="col"></div>
<div class="col">
<form action="#" method="POST">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" name="email">
</div>
<div class="form-group">
<label for="exampleInputPassword1">密码</label>
<input type="password" name="password" class="form-control" id="exampleInputPassword1">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">立即登录</button>
</div>
</form>
</div>
<div class="col"></div>
</div>
{% endblock %}
效果图
后端
校验模板
forms.py
import wtforms
from wtforms.validators import Email, Length, EqualTo
# 导入数据库模型
from models import UserModel, EmailCaptchaModel
from exts import db
# 登录逻辑的校验
class LoginForm(wtforms.Form):
email = wtforms.StringField(validators=[Email(message="邮箱格式错误,请重新输入!")])
password = wtforms.StringField(validators=[Length(min=8, max=20, message="密码格式错误,8-20位")])
后端登录逻辑
auth.py
@bp.route("/login", methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template("login.html")
else:
form = LoginForm(request.form)
# 校验部分
if form.validate():
# 先从前端获取变量
email = form.email.data
password = form.password.data
# 在数据库中查找比对
user = UserModel.query.filter_by(email=email).first()
if not user:
print("邮箱在数据库中不存在!")
return render_template("login.html")
# 验证密码
# user.password 是从数据库中查询到的加密的密码, password是从前端输入的没有加密的密码
if check_password_hash(user.password, password):
# 这里引入cookie和session,cookie存储少量的数据,cookie一般用于存储登录授权的数据
# flask中的session是加密以后存储在cookie中的。
session['user_id'] = user.id
return "登录成功!"
else:
print("密码错误!")
return render_template("login.html")
效果图
登录cookie相关
登录前没有cookie
登录后的cookie
关于cookie相关的报错及解决
显示未设置secret_key,需要在config.py中添加一个对象
设置的字段不要太短容易被爆破,设置的key记得保密。
例如: