前言
之前在课设写过一个人事管理系统里面也有写登录和注册,但是我将里面的登录注册代码单独拿出来后发现登录以后无法进行认证也就是 is_authenticated
一直为false,于是就开始查找问题.
之前用的是flask-security
它可以实现用户的权限进行登录注册,这次的不需要用户权限设想就问题可能出在要设置权限,我感觉应该不是以后在做问题的查找.
于是我换成了flask-login
去实现登录和注册
具体代码
app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
# 实例初始化环境信息文件
app = Flask(__name__)
app.config['SECRET_KEY'] = 'xxx' # 等同于 app.secret_key = 'dev' 设置签名所需的钥匙
login_manager = LoginManager()
login_manager.init_app(app) # 实例化扩展类
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://xx:xx@xxxxxxxx/user'
# 格式 mysql://名称:密码@IP/数据库
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 关闭对模型修改的监控
app.jinja_env.auto_reload = True
app.config['TEMPLATES_AUTO_RELOAD'] = True
# 热更新HTML模板文件
db = SQLAlchemy(app)
# 在扩展类实例化前加载配置
login_manager.login_view = 'login' # 定义错误提示信息
login_manager.login_message_category = 'info'
login_manager.login_message = 'Access denied.'
@login_manager.user_loader
def load_user(user_id): # 创建用户加载回调函数,接受用户ID作为参数
from models import User
user = User.query.get(int(user_id)) # 用ID作为user模型的主键查询对应的用户
return user # 返回用户对象
import views, errors, forms
errors.py
from app import app
from flask import render_template
# 错误状态处理文件
@app.errorhandler(404) # 传入要处理的错误代码
def page_not_found(e): # 接受异常对象作为参数
return render_template('404.html'), 404 # 返回模板和状态码
@app.errorhandler(400) # 传入要处理的错误代码
def page_not_found(e): # 接受异常对象作为参数
return render_template('400.html'), 400 # 返回模板和状态码
@app.errorhandler(500) # 传入要处理的错误代码
def page_not_found(e): # 接受异常对象作为参数
return render_template('500.html'), 500 # 返回模板和状态码
forms.py
from flask_wtf import FlaskForm # FlaskForm 为表单基类
from wtforms import StringField, PasswordField, SubmitField # 导入字符串字段,密码字段,提交字段
from wtforms.validators import DataRequired, ValidationError
class LoginForm(FlaskForm):
account = StringField(
# 标签
label="账号",
# 验证器
validators=[
DataRequired('请输入用户名')
],
description="账号",
# 附加选项,会自动在前端判别
render_kw={
"class": "form-control",
"placeholder": "请输入账号!",
"required": 'required' # 表示输入框不能为空,并有提示信息
}
)
pwd = PasswordField(
# 标签
label="密码",
# 验证器
validators=[
DataRequired('请输入密码')
],
description="密码",
# 附加选项(主要是前端样式),会自动在前端判别
render_kw={
"class": "form-control",
"placeholder": "请输入密码!",
"required": 'required' # 表示输入框不能为空
}
)
submit = SubmitField(
label="登录",
render_kw={
"class": "btn btn-primary btn-block btn-flat",
}
)
models.py
from app import db
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash # 生成密码散列值函数
# 创建数据模型对象
class User(UserMixin, db.Model): # 用户
id = db.Column(db.Integer, primary_key=True)
userID = db.Column(db.Integer, nullable=False)
password = db.Column(db.String(128), nullable=False)
phone = db.Column(db.BigInteger, nullable=False, unique=True)
email = db.Column(db.String(50), nullable=False, unique=True)
active = db.Column(db.Boolean())
def set_password(password): # 用来设置密码的方法,接受密码作为参数
return generate_password_hash(password) # 将生产的密码保持到对应的字段
def validate_password(self, password): # 用于验证密码的方法,接受密码作为参数
return check_password_hash(self.password, password)
# 返回布尔值
# db.create_all()
views.py
from app import app, db
from models import User
from flask import request, url_for, redirect, flash, render_template
from flask_login import login_user, logout_user,current_user
import forms
# 后端处理文件
@app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
# -----------------------------------------------
@app.route('/user/login', methods=['GET', 'POST'])
def login(): # 登录
if not current_user.is_anonymous:
return redirect(url_for('index'))
form = forms.LoginForm()
if request.method == 'POST':
userID = request.form.get('userID')
password = request.form.get('password')
if not userID or not password:
flash('请输入')
return redirect(url_for('login'))
user = User.query.filter_by(userID=userID).first()
if user is None:
flash('用户名错误')
return redirect(url_for('login'))
if not user.validate_password(password):
flash('密码错误')
return redirect(url_for('login'))
flash('登录成功')
login_user(user,remember=True)
return redirect(url_for('index'))
return render_template('login.html', form=form)
@app.route('/logging', methods=['GET', 'POST'])
def logging(): # 注册
if not current_user.is_anonymous:
return redirect(url_for('index'))
if request.method == 'POST':
userID = request.form.get('userID')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
phone = request.form.get('phone')
user_phone = User.query.filter_by(phone=phone).first()
if user_phone is not None:
flash('手机号已被注册')
return redirect(url_for('logging'))
email = request.form.get('email')
user_email = User.query.filter_by(email=email).first()
if user_email is not None:
flash('邮箱已被注册')
return redirect(url_for('logging'))
if password1 != password2:
flash('两次输入的密码不同')
return redirect(url_for('logging'))
user = User.query.filter_by(userID=userID).first()
if user is not None:
flash('用户已注册')
return redirect(url_for('login'))
new_user = User(userID=userID, password=User.set_password(password1), phone=phone, email=email)
db.session.add(new_user)
db.session.commit()
flash('注册成功')
login_user(new_user)
return redirect(url_for('index'))
return render_template('logging.html')
@app.route('/logout')
def logout(): # 登出
logout_user()
flash('登出')
return redirect(url_for('index'))
具体的html文件就不放出来了
注意!!!
在models
中 用户表需要创建 active
字段.