flask 中几种在所有请求之前进行验证的方法之间的差别

2017-09-25  本文已影响821人  那未必

在所有请求之前添加钩子

在做验证是否是登陆用户之类的功能时,一定会涉及到与此相关的知识点。

对于直接用 app.add_url_rule() 或者使用 @app.route(...) 的方式来定义路由的情况,我们可以使用@app.before_request() 装饰器来实现在所有请求之前执行某一些验证逻辑代码。

但是对于用blueprint来定义各种路由的方式,blueprint.before_request 不再是一个装饰器,而是一个函数,并且接受一个参数,参数是一个方法名 func。也就是在执行所有请求之前会先执行这个 func 方法

最基本的代码是:

def blueprint_validate_session_in_stock():
    print 'this is [before_request] in blueprint'

def create_app(config_name):
    app=Flask(__name__)
    app.config.from_object(config.config['base'])

    stocks_blueprint.before_request(
        blueprint_validate_session_in_stock)

    app.register_blueprint(main_blueprint)
    app.register_blueprint(stocks_blueprint)

    return app

这样的话,每次访问 stocks_blueprint 模块中的页面,都会打印:this is [before_request] in blueprint

一个有益的对比

由于 blueprint 不仅有 before_request() 方法,还有 before_app_request() 方法,还有 before_app_first_request() 方法,再加上在 app 层面还有 app.before_request() 方法。这四种方法究竟在哪些情况下执行?谁先谁后?这些问题都将直接影响到网站访问控制的逻辑,如果理解错误,还可能造成一些访问的死循环。

我们将前面的代码改为:

#encoding:utf8

from flask import Flask,redirect
import config

from controllers import main_blueprint
from controllers.stocks import stocks_blueprint


def validate_session():
    print 'over the top! this is before_request\n'
def blueprint_validate_app_session_in_stock():
    print '\tthis is [before_app_request] in blueprint\n'
def blueprint_validate_app_session_first_in_stock():
    print '\tthis is [before_app_first_request] in blueprint\n'
def blueprint_validate_session_in_stock():
    print '\tthis is [before_request] in blueprint\n'
    session=None
    if session==None:
        return redirect('/login')

def create_app(config_name):
    app=Flask(__name__)
    app.config.from_object(config.config['base'])

    app.before_request(validate_session)
    stocks_blueprint.before_request(
        blueprint_validate_session_in_stock)
    stocks_blueprint.before_app_first_request(
        blueprint_validate_app_session_first_in_stock
    )
    stocks_blueprint.before_app_request(
        blueprint_validate_app_session_in_stock)

    app.register_blueprint(main_blueprint)
    app.register_blueprint(stocks_blueprint)

    # print app.url_map
    return app

代码的意图是:访问 blueprint_stock 的根页面时,要做 session 验证,如果没有 session 就跳转到 login 页面去

我们首先访问网站根页面,然后点击跳转到 stock 页面,所看到的打印记录是:

# 这是访问网站根页面的反馈

    this is [before_app_first_request] in blueprint

over the top! this is before_request

        this is [before_app_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:45:59] "GET / HTTP/1.1" 200 -

# 这是访问 stock 根页面的反馈

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:46:01] "GET /stocks/ HTTP/1.1" 302 -

# 这是跳转到 login 页面的反馈

over the top! this is before_request

        this is [before_app_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:46:01] "GET /login HTTP/1.1" 200 -

从上面的打印结果来对比,可以得出如下结论:

关于页面刷新

如果用户停留在某一页面,只是在浏览器上点击了刷新,会有什么效果呢?我们将上面的代码中验证 session 不存在就跳转的 login 页面的代码去掉后,即注释掉这部分代码:

#session=None
#    if session==None:
#        return redirect('/login')

直接访问 blueprint_stock 的根页面来查看一下打印结果:

# 这是第一次访问的打印结果

        this is [before_app_first_request] in blueprint

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:56:25] "GET /stocks/ HTTP/1.1" 200 -

# 这是用户点击刷新后的打印结果:

over the top! this is before_request

        this is [before_app_request] in blueprint

        this is [before_request] in blueprint

127.0.0.1 - - [25/Sep/2017 11:56:48] "GET /stocks/ HTTP/1.1" 200 -

可以看到,刷新后有两个变化:

结论

上一篇 下一篇

猜你喜欢

热点阅读