Python-Flask框架,flask_login插件,登入登出,实现视图保护

 

前言

在规划一个web的时候,肯定会遇到这种情况,有一些页面不能让未登入的用户访问,这个时候那些页面就要进行视图保护。

编写示例代码

现在就以登陆和登出为例子
在登出视图函数上做视图保护,就和前言中的解释类似,登陆了的用户可以访问登出视图,未登录的用户要先登陆才能登出

初始化app

from flask import Flask, url_for, render_template, flash
from flask_login import LoginManager, current_user, login_user, login_required, logout_user
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length

app = Flask(__name__)

login_manager = LoginManager(app)
bootstrap = Bootstrap(app)

'''
当然也可以利用init_app
login_manager = LoginManager()
login_manager.init_app(app)
Bootstrap()同理
'''
class LoginForm(FlaskForm):
    username = StringField('Username',validators=[DataRequired(),Length(1,20)])
    password = PasswordField('Password',validators=[DataRequired(),Length(8,128)])
    remember = BooleanField('Remember me')
    submit = SubmitField('Sign in')
    
def redirect_back(default='blog.index', **kwargs):
    '''函数功能: 放回上一页'''
    for target in request.args.get('next'), request.referrer:
        if not target:
            continue
        if is_safe_url(target):
            return redirect(target)
    return redirect(url_for(default, **kwargs))

登录视图函数

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return 'success login, you can enjoy it'
    form = LoginForm()

    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        remember = form.remember.data
        admin = Admin.query.first()
        if admin:
            # 验证用户名和密码
            if username == admin.name and admin.password:
                login_user(admin, remember)
                return "success login"
        else:
            return "账号或者密码错误"
    return render_template('login.html', form=form)

login.html

{% from 'bootstrap/form.html' import render_form %}

    <div>
        <div>
            <h1>Log in</h1>
        </div>
        <div>
            {{ render_form(form, extra_classes='col-6') }}
        </div>
    </div>

登出函数

@app.route("/logout")
@login_required
def logout():
    logout_user()
    flash("Logout success.", 'info')
    return redirect_back()

登出函数既要实现登出功能也要对其视图保护
其中
@login_required就是用于标明需要视图保护的视图
所以只要实现了flask_login的初始化,就可以可插拔的进行添加视图保护,十分方便。
例如

@app.route('/hello_1')
@login_required
def hello_1():
    return "hello_1"


@app.route('/hello_2')
def hello_2():
    return "hello_2"

当访问http://localhost/hello_1的时候 只有登入了才能看到hello_1,
访问/hello_2的时候 就直接可以看到hello_2

添加视图保护内容

......
login_manager = LoginManager(app)
login_manager.login_view = 'login'# 指定视图保护的视图函数
login_manager.login_message_category = 'warning'
# login_manager.login_message = u'请先登录!'
# 当用户没有登陆 却要访问需要登陆的url  就会跳转到视图保护的页面

login_manager.login_view 即是指定视图保护所跳转的视图函数,在这里是登入视图函数
login_manager.login_message 可以指定f消息内容,默认为"Please log in to access this."
login_manager.login_message_category 指定消息的类别,默认为"message"


整理代码

.
├── app.py
└── templates
└── login.html

app.py

from flask import Flask, url_for, render_template, flash
from flask_login import LoginManager, current_user, login_user, login_required, logout_user, UserMixin
from flask_bootstrap import Bootstrap
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length
import os

basedir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

app = Flask(__name__)
# SECRET_KEY =
app.config['SECRET_KEY'] = "hello flask login"
app.config['SQLALCHEMY_DATABASE_URI']= 'sqlite:///' + os.path.join(basedir, 'data-dev.db')

login_manager = LoginManager(app)
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)

login_manager.login_view = 'login'# 指定视图保护的视图函数
login_manager.login_message_category = 'warning'



'''
当然也可以利用init_app
login_manager = LoginManager()
login_manager.init_app(app)
Bootstrap()同理
'''


class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(1, 20)])
    password = PasswordField('Password', validators=[DataRequired(), Length(8, 128)])
    remember = BooleanField('Remember me')
    submit = SubmitField('Sign in')

class Admin(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), unique=True)
    password = db.Column(db.String(50))


def init():
    '''building, kiesblog, just for you '''
    db.drop_all()
    db.create_all()
    admin = Admin.query.first()
    admin = Admin(name="admin",
                  password="password")
    db.session.add(admin)
    db.session.commit()
init()

@login_manager.user_loader
def load_user(userid):
    return User.get(userid)

@app.route('/')
@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return 'success login, you can enjoy it'
    form = LoginForm()

    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        remember = form.remember.data
        admin = Admin.query.first()
        if admin:
            # 验证用户名和密码
            if username == admin.name and admin.password:
                login_user(admin, remember)
                return "success login"
        else:
            return "账号或者密码错误"
    return render_template('login.html', form=form)

@app.route("/logout")
@login_required
def logout():
    logout_user()
    return "logout success"

@app.route('/hello_1')
@login_required
def hello_1():
    return "hello_1"


@app.route('/hello_2')
def hello_2():
    return "hello_2"

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=80)

login.html

{% from 'bootstrap/form.html' import render_form %}

    <div>
        <div>
            <h1>Log in</h1>
        </div>
        <div>
            {{ render_form(form, extra_classes='col-6') }}
        </div>
    </div>

账号密码分别为 admin password

ps: 此为示例代码,未对password进行hash加密,如有需要请自行添加!
好了,可以开始你的测试了????

关于作者

Python-Flask框架(五),flask_login插件,登入登出,实现视图保护_Python