Flask-登录之falsk-login

背景

flask如何将部分页面鉴权后才能访问,笔者通过Flask-login实现,下面一起来看看是如何实现的吧。

系统环境

  • win-11
  • python 3.8

依赖安装

pip install flask
pip install flask-login
pip install flask-sqlalchemy
pip install sqlalchemy-utils
pip install click
pip install Werkzeug

页面展示

登录页面

在这里插入图片描述

登陆后页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CAzveLC5-1660818099443)(picture/Pasted%20image%2020220818180222.png)]

导入bootstrap依赖 和 html页面

# 新一个文件夹
# 新文件夹下创建staice文件夹用于存放bootstrap依赖,文件夹下再创建三个文件夹为:css、js、images
# 新文件夹下创建templates文件夹用于存放html文件
# 相关文件请通过云盘下载

# 文件目录结构
├─static
│  ├─css
│  ├─images
│  └─js
├─templates

配置app.py文件

导入相关模块,定义secrets 并配置ORM

from flask import Flask, render_template, request, redirect, url_for, flash  
from flask_sqlalchemy import SQLAlchemy  
from werkzeug.security import generate_password_hash, check_password_hash  
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin  
import sqlalchemy_utils  
import os  
import sys  
import click 
  
app = Flask(__name__)  

'''
自动生成secret
import secrets  
print(secrets.token_hex(32))
'''
app.secret_key = b'12313123131241414141241fsfgsfsdfsfs'  
  
# 判断系统类型  
WIN = sys.platform.startswith('win')  
if WIN:  # 如果是 Windows 系统,使用三个斜线  
    prefix = 'sqlite:///'  
else:  # 否则使用四个斜线  
    prefix = 'sqlite:'  
  
# sqlite:///数据库文件的绝对地址,如果你使用 Windows 系统只需要写入三个斜线(即 sqlite:///)  
app.config['SQLALCHEMY_DATABASE_URI'] = prefix + os.path.join(app.root_path, 'data.db')  
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 关闭对模型修改的监控  
db = SQLAlchemy(app)  
login_manager = LoginManager(app)  
login_manager.login_view = 'login'  
  
  
class User(db.Model, UserMixin):  
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  
    user_type = db.Column(db.String(255))  
    username = db.Column(db.String(255))  
    password_hash = db.Column(db.String(128))  # 密码散列值  
  
    def set_password(self, password):  # 用来设置密码的方法,接受密码作为参数  
        self.password_hash = generate_password_hash(password)  # 将生成的密码保持到对应字段  
  
    def validate_password(self, password):  # 用于验证密码的方法,接受密码作为参数  
        return check_password_hash(self.password_hash, password)  # 返回布尔值  

定义手动创建管理用户模块

# 使用 click.option() 装饰器设置的两个选项分别用来接受输入用户名和密码。执行 flask admin 命令,输入用户名和密码后,即可创建管理员账户。  
@app.cli.command()  
@click.option('--username', prompt=True, help='The username used to login.')  
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True, help='The password used to login.')  
def admin(username, password):  
    """Create user."""  
    # 判断数据库是否存在
    if sqlalchemy_utils.functions.database_exists(prefix + os.path.join(app.root_path, 'data.db')):  
        print('Database already exists.')  
    else:  
        print('Create database.')  
        db.create_all()  
  
    if db.session.query(User.id).filter_by(username=username).scalar() is not None:  
        user = User.query.filter_by(username=username).first()  
        click.echo('Updating user...')  
        user.set_password(password)  # 设置密码  
    else:  
        click.echo('Creating user...')  
        user = User(username=username, user_type='Admin')  
        user.set_password(password)  # 设置密码  
        db.session.add(user)  
  
    db.session.commit()  # 提交数据库会话  
    click.echo('Done.')

创建与更新管理用户

在这里插入图片描述

定义登录与退出函数

通过@login_required 装饰器保护相应模块

@login_manager.user_loader  
def load_user(user_id):  # 创建用户加载回调函数,接受用户 ID 作为参数  
    user = User.query.get(int(user_id))  # 用 ID 作为 User 模型的主键查询对应的用户  
    return user  # 返回用户对象  
  
  
@app.route('/', methods=['GET', 'POST'])  
@login_required   # 用于视图保护 
def index():  
    if request.method == "GET":  
        return render_template('index.html')  
  
  
@app.route('/login', methods=['GET', 'POST'])  
def login():  
    if request.method == 'POST':  
        username = request.form['username']  
        password = request.form['password']  
  
        if not username or not password:  
            flash('Invalid input.')  
            return redirect(url_for('login'))  
        user = User.query.filter_by(username=username).first()  
        # 验证用户名和密码是否一致  
  
        if username == user.username and user.validate_password(password):  
            login_user(user)  # 登入用户  
            # flash('Login success.')  
            return redirect(url_for('index'))  # 重定向到主页  
  
        flash('Invalid username or password.')  # 如果验证失败,显示错误消息  
        return redirect(url_for('login'))  # 重定向回登录页面  
  
    return render_template('login.html')  
  
  
@app.route('/logout')  
@login_required 
def logout():  
    logout_user()  # 登出用户  
    flash('Goodbye.')  
    return redirect(url_for('login'))  # 重定向回首页

完整app.py 文件

from flask import Flask, render_template, request, redirect, url_for, flash  
from flask_sqlalchemy import SQLAlchemy  
from werkzeug.security import generate_password_hash, check_password_hash  
from flask_login import LoginManager, login_user, login_required, logout_user, UserMixin  
import sqlalchemy_utils  
import os  
import sys  
import click  
  
app = Flask(__name__)  
app.config['SECRET_KEY'] = '365818fd398f1bc6db5743907791d6c067e9c8362a8d742d74c6e1c811f2abbf'  
  
# 判断系统类型  
WIN = sys.platform.startswith('win')  
if WIN:  # 如果是 Windows 系统,使用三个斜线  
    prefix = 'sqlite:///'  
else:  # 否则使用四个斜线  
    prefix = 'sqlite:'  
  
# sqlite:///数据库文件的绝对地址,如果你使用 Windows 系统只需要写入三个斜线(即 sqlite:///)  
app.config['SQLALCHEMY_DATABASE_URI'] = prefix + os.path.join(app.root_path, 'data.db')  
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 关闭对模型修改的监控  
db = SQLAlchemy(app)  
login_manager = LoginManager(app)  
login_manager.login_view = 'login'  
  
  
class User(db.Model, UserMixin):  
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  
    user_type = db.Column(db.String(255))  
    username = db.Column(db.String(255))  
    password_hash = db.Column(db.String(128))  # 密码散列值  
  
    def set_password(self, password):  # 用来设置密码的方法,接受密码作为参数  
        self.password_hash = generate_password_hash(password)  # 将生成的密码保持到对应字段  
  
    def validate_password(self, password):  # 用于验证密码的方法,接受密码作为参数  
        return check_password_hash(self.password_hash, password)  # 返回布尔值  
  
  
# 使用 click.option() 装饰器设置的两个选项分别用来接受输入用户名和密码。执行 flask admin 命令,输入用户名和密码后,即可创建管理员账户。  
@app.cli.command()  
@click.option('--username', prompt=True, help='The username used to login.')  
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True, help='The password used to login.')  
def admin(username, password):  
    """Create user."""  
    # 判断数据库是否存在  
    if sqlalchemy_utils.functions.database_exists(prefix + os.path.join(app.root_path, 'data.db')):  
        print('Database already exists.')  
    else:  
        print('Create database.')  
        db.create_all()  
  
    if db.session.query(User.id).filter_by(username=username).scalar() is not None:  
        user = User.query.filter_by(username=username).first()  
        click.echo('Updating user...')  
        user.set_password(password)  # 设置密码  
    else:  
        click.echo('Creating user...')  
        user = User(username=username, user_type='Admin')  
        user.set_password(password)  # 设置密码  
        db.session.add(user)  
  
    db.session.commit()  # 提交数据库会话  
    click.echo('Done.')  
  
  
@login_manager.user_loader  
def load_user(user_id):  # 创建用户加载回调函数,接受用户 ID 作为参数  
    user = User.query.get(int(user_id))  # 用 ID 作为 User 模型的主键查询对应的用户  
    return user  # 返回用户对象  
  
  
@app.route('/', methods=['GET', 'POST'])  
@login_required  
def index():  
    if request.method == "GET":  
        return render_template('index.html')  
  
  
@app.route('/login', methods=['GET', 'POST'])  
def login():  
    if request.method == 'POST':  
        username = request.form['username']  
        password = request.form['password']  
  
        if not username or not password:  
            flash('Invalid input.')  
            return redirect(url_for('login'))  
        user = User.query.filter_by(username=username).first()  
        # 验证用户名和密码是否一致  
  
        if username == user.username and user.validate_password(password):  
            login_user(user)  # 登入用户  
            # flash('Login success.')  
            return redirect(url_for('index'))  # 重定向到主页  
  
        flash('Invalid username or password.')  # 如果验证失败,显示错误消息  
        return redirect(url_for('login'))  # 重定向回登录页面  
  
    return render_template('login.html')  
  
  
@app.route('/logout')  
@login_required  # 用于视图保护,后面会详细介绍  
def logout():  
    logout_user()  # 登出用户  
    flash('Goodbye.')  
    return redirect(url_for('login'))  # 重定向回首页  
  
  
if __name__ == '__main__':  
    app.run()
    

html、css、js 文件下载

百度网盘:链接:https://pan.baidu.com/s/1CfEvY1xjbcn9pKAkwDRIsQ 提取码:3d4q
阿里云盘:https://www.aliyundrive.com/s/GDksRTRvR5x

参考文章:
https://tutorial.helloflask.com/
https://flask-login.readthedocs.io/en/latest/
https://sqlalchemy-utils.readthedocs.io/en/latest/

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值