Python:Flaks实现登录验证

1.登录验证初始化

from flask import Flask, session, g
from flask_login import LoginManager

from models import db, User
from accounts.views import accounts
from qa.views import qa
from utils.filters import number_split

app = Flask(__name__, static_folder='assets')
# 从配置文件加载配置
app.config.from_object('conf.Config')

# 数据库初始化
db.init_app(app)

# 登录验证初始化
login_manager = LoginManager()
login_manager.login_view = "accounts.login"
login_manager.login_message = '请登录'
login_manager.login_message_category = "danger"
login_manager.init_app(app)

# 注册蓝图
app.register_blueprint(accounts, url_prefix='/accounts')
app.register_blueprint(qa, url_prefix='/')

# 注册过滤器
app.jinja_env.filters['number_split'] = number_split

#
# @app.before_request
# def before_request():
#     """ 如果有用户id,设置到全局对象 """
#     user_id = session.get('user_id', None)
#     if user_id:
#         user = User.query.get(user_id)
#         print(user)
#         g.current_user = user

#实现登录验证,操作必须登录才可以
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)

2.视图函数中添加

@login_required
from flask import Blueprint, render_template, request, abort
from flask_login import login_required

from models import Question

qa = Blueprint("qa", __name__, template_folder="templates", static_folder="../assets")


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


@qa.route('/follow')
def follow():
    """ 关注 """
    # 每页数据的大小
    per_page = 20
    page = int(request.args.get('page', 1))
    page_date = Question.query.filter_by(is_valid=True).paginate(page=page, per_page=per_page)
    return render_template('follow.html', page_date=page_date)


@qa.route('/write')
@login_required
def write():
    """ 写文章,提问 """
    return render_template('write.html')


@qa.route('/detail/<int:q_id>')
def detail(q_id):
    """ 问题详情 """
    # 查询问题信息
    question = Question.query.get(q_id)
    # 当文章被删除,返回404
    if not question.is_valid:
        abort(404)
    # 2.展示第一条回答信息
    answer = question.answer_list.filter_by(is_valid=True).first()
    return render_template('detail.html', question=question, answer=answer)

3.在对应的表单中或视图函数中调用

flask_login提供的login_user方法传入user对象
import hashlib

from flask import request
from flask_login import login_user
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, ValidationError
from wtforms.validators import DataRequired, Length, EqualTo

from models import User, db, UserProfile, UserLoginHistory
from utils import constans
from utils.validators import phone_required


class RegisterForm(FlaskForm):
    """用户注册"""
    # render_kw添加其余属性,如bootstarp中的class属性或样式,或默认值
    username = StringField(label='用户名', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请输入用户名'
    }, validators=[DataRequired('请输入用户名'), phone_required])
    nickname = StringField(label='昵称', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请输入昵称'
    }, validators=[DataRequired('请输入昵称'), Length(min=2, max=20, message='昵称长度在2~20之间')])
    password = PasswordField(label='密码', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请输入密码'
    }, validators=[DataRequired('请输入密码')])
    confirm_password = PasswordField(label='确认密码', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请确认密码'
    }, validators=[DataRequired('请输入确认密码'), EqualTo('password', message='二次密码输入不一致')])


    def validate_username(self, field):
        """检测用户名是否已经存在"""
        user = User.query.filter_by(username=field.data).first()
        if user:
            raise ValidationError("用户名已存在")
        return field


    def register(self):
        """用户注册方法"""
        # 1.获取表单数据
        username = self.username.data
        nickname = self.nickname.data
        password = self.password.data
        # 2.构建用户对象
        try:
            # 将密码加密存储
            password = hashlib.sha256(password.encode()).hexdigest()
            user_obj = User(
                username=username,
                nickname=nickname,
                password=password
            )
            db.session.add(user_obj)
            profile = UserProfile(username=username, user=user_obj)
            db.session.add(profile)
            # 3.提交到数据库
            db.session.commit()
            return user_obj
        except Exception as e:
            print(e)
        return None


class loginForm(FlaskForm):
    """用户登录"""
    # render_kw添加其余属性,如bootstarp中的class属性或样式,或默认值
    username = StringField(label='用户名', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请输入用户名'
    }, validators=[DataRequired('请输入用户名'), phone_required])

    password = PasswordField(label='密码', render_kw={
        'class': 'form-control input-lg',
        'placeholder': '请输入密码'
    }, validators=[DataRequired('请输入密码')])


    def validate(self):
        print('自动执行???')
        result = super().validate()
        username = self.username.data
        password = self.password.data
        if result:
            # TODO 验证加密后的密码是否正确
            user = User.query.filter_by(username=username, password=password).first()
            if user is None:
                result = False
                # 未验证通过,给username一个指定的错误信息
                self.username.errors = ['用户名或密码错误']
            elif user.status == constans.UserStatus.USER_IN_ACTIVE.value:
                result = False
                # 未验证通过,给username一个指定的错误信息
                self.username.errors = ['用户已被禁用']
        return result


    def do_login(self):
        try:
            username = self.username.data
            password = self.password.data
            # 1.查找用户
            # TODO 验证加密后的密码是否正确
            user = User.query.filter_by(username=username, password=password).first()
            # 2.登录用户
            # session['user_id'] = user.id
            # 3.调用login_user
            login_user(user)
            ip = request.remote_addr
            ua = request.headers.get('user-agent', None)
            obj = UserLoginHistory(username=username, ip=ip, ua=ua, user=user)
            db.session.add(obj)
            db.session.commit()
            return user
        except Exception as e:
            print(e)
        return None

 4.退出参考官网

当用户准备退出时:

 
 

 直接调用login_user()他们将被注销,并且他们会话的所有 cookie 都将被清除。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值