Flask基于flask_login实现登录、验证码

发布于:2024-04-15 ⋅ 阅读:(190) ⋅ 点赞:(0)

flask_login 是一个 Flask 扩展,用于在 Flask web 应用中实现用户会话管理。它允许你跟踪哪些用户已经登录,并管理他们的登录状态。flask_login 提供了用户认证的基础结构,但具体的用户验证(如用户名和密码检查)和存储(如数据库)需要你自行实现。

以下是 flask_login 的一些主要特性和功能:
用户登录和注销:提供用户登录和注销的接口。
用户认证:通过装饰器(如 @login_required)确保只有已登录的用户才能访问特定的视图或路由。
用户会话管理:管理用户的登录状态,并提供一个安全的方式来跟踪用户会话。
用户信息:提供一个方式来获取当前登录用户的信息。

依赖

flask
flask_wtf
flask_sqlalchemy
captcha
werkzeug

效果

1

入口app

实现用户登录和注销的逻辑。这通常涉及到验证用户的凭据(如用户名和密码),并设置或清除用户的登录状态。

app.py

import random
import string

from flask import Flask, redirect, url_for, render_template, flash, session, Response
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from models import User, db
from LoginForm import LoginForm
from captcha.image import ImageCaptcha

login_manager = LoginManager()
image = ImageCaptcha()

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://user:pass@127.0.0.1/db"
app.config['SECRET_KEY'] = 'sd23rhewer'
login_manager.init_app(app)
login_manager.login_view = 'login'
db.init_app(app)


def generate_captcha():
    """
    生成验证码文字
    """
    characters = string.ascii_letters + string.digits
    captcha = ''.join(random.choice(characters) for i in range(4))
    return captcha


@login_manager.user_loader
def load_user(user_id):
    """
    加载用户
    """
    return User.query.get(int(user_id))


@app.route("/")
def index():
    """
    前台首页
    """
    return render_template('index.html')


@app.route('/dashboard')
@login_required
def dashboard():
    """
    后台首页
    """
    return render_template('dashboard.html', current_user=current_user)


@app.route('/login', methods=['GET', 'POST'])
def login():
    """
    登录
    """
    form = LoginForm()
    if form.validate_on_submit():

        captcha_session = session.get('capcha', '')
        print(captcha_session, '  ', form.captcha.data)
        if captcha_session.lower() != form.captcha.data.lower():
            flash("验证码错误")
            return redirect(url_for('login'))

        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash("用户名或密码错误")
            return redirect(url_for('login'))
        login_user(user, remember=True)
        return redirect(url_for('dashboard'))
    return render_template('login.html', form=form)


@app.route('/captcha_image', methods=['GET', 'POST'])
def captcha_image():
    """
    验证码图片
    """
    captcha = generate_captcha()
    session['capcha'] = captcha
    data = image.generate(captcha)
    print(captcha)
    return Response(data, mimetype="image/png")


@app.route('/logout', methods=['GET', 'POST'])
def logout():
    """
    退出
    """
    logout_user()
    return redirect(url_for('index'))

表单

LoginForm.py

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField
from wtforms.validators import DataRequired


class LoginForm(FlaskForm):
    username = StringField('用户名', validators=[DataRequired('输入用户名')])
    password = PasswordField('密码', validators=[DataRequired('输入密码')])
    captcha = StringField('验证码', validators=[DataRequired('输入验证码')])
    submit = SubmitField('提交')

数据库模型

在你的 Flask 应用中,你需要配置 flask_login,并定义一个用户类。这个用户类通常继承自 UserMixin,它提供了默认的用户属性和方法。

models.py

# coding: utf-8
from flask_login import UserMixin
from sqlalchemy import Column, DateTime, String, text
from sqlalchemy.dialects.mysql import INTEGER
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemy


db = SQLAlchemy(engine_options={'pool_pre_ping': True})


class User(UserMixin, db.Model):
    __tablename__ = 'xt_user'

    id = Column(INTEGER(11), primary_key=True)
    username = Column(String(50, 'utf8_unicode_ci'))
    password = Column(String(1024, 'utf8_unicode_ci'))
    create_at = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"))

    def set_password(self, password):
        self.password = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password, password)

模板

templates/login.html

{% with messages = get_flashed_messages() %}
  {% if messages %}
    <ul class=flashes>
    {% for message in messages %}
      <li>{{ message }}</li>
    {% endfor %}
    </ul>
  {% endif %}
{% endwith %}
<form method="POST">
    {{ form.hidden_tag() }}
    <p>
        {{ form.username.label }}<br>
        {{ form.username() }}
    </p>
    <p>
        {{ form.password.label }}<br>
        {{ form.password() }}
    </p>
    <p>
        {{ form.captcha.label }}<br>
        {{ form.captcha() }}
        <img src="{{ url_for('captcha_image') }}" alt="Captcha" width="200", height="70">
    </p>
    <p>{{ form.submit() }}</p>
</form>

templates/dashboard.html

在视图函数中,你可以使用 current_user 对象来获取当前登录用户的信息。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>面板</title>
</head>
<body>
<p>您好,{{ current_user.username }}&nbsp;<a href="/logout">退出</a></a></p>
</body>
</html>

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p><a href="/login">登录</a></a></p>
</body>
</html>

初始化数据

from flask import Flask
from werkzeug.security import generate_password_hash

from models import db, User

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://user:pass@127.0.0.1/db"
db.init_app(app)


def init_data():
    u1 = User(username='abc', password=generate_password_hash('123'))
    db.session.add_all([u1])
    db.session.commit()


with app.app_context() as context:
    init_data()

参考

https://flask-login.readthedocs.io/en/latest/


网站公告

今日签到

点亮在社区的每一天
去签到