Python-Flask框架(五),flask_login插件,登入登出,實現視圖保護

前言

在規劃一個web的時候,肯定會遇到這種情況,有一些頁面不能讓未登入的用戶訪問,這個時候那些頁面就要進行視圖保護。

flask_login是一個十分方便且優秀的flask插件,更多內容請查閱flask_login官方文檔

編寫示例代碼

現在就以登陸和登出爲例子
在登出視圖函數上做視圖保護,就和前言中的解釋類似,登陸了的用戶可以訪問登出視圖,未登錄的用戶要先登陸才能登出

初始化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"

更多內容請關注 flask_login官方文檔

整理代碼

.
├── 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加密,如有需要請自行添加!
好了,可以開始你的測試了😄

關於作者

如有更多的問題,請聯繫我[email protected]

你也可以通過 github | csdn | @新浪微博 關注我的動態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章