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

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

作者: 那未必 | 来源:发表于2017-09-25 17:15 被阅读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 -

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

  • blueprint.before_app_request 会影响全局,即访问网站根页面或其他页面时,它都会生效

  • blueprint.before_app_request 会最先执行,先于 app.before_request

  • blueprint.before_app_first_request 会影响全局,但是只执行一次,适合用在初始化某些变量,它的执行顺序是在 app.before_request 之后

  • blueprint.before_app_request 要慎用,假如上面的代码中将验证 session 不存在就跳转到 login 页面的逻辑代码,写在了 blueprint_validate_app_session_in_stock() 中,就会造成访问的死循环! 因为访问 login 页面时,这个验证的逻辑代码同样会生效:发现没有 session,又一次跳转到 login 页面,造成页面一直在刷新!

关于页面刷新

如果用户停留在某一页面,只是在浏览器上点击了刷新,会有什么效果呢?我们将上面的代码中验证 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 -

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

  • 执行顺序变了,刷新后首先执行的是 app.before_request
  • 刷新后 blueprint.before_app_first_request 不执行了,这个很好理解

结论

  • 一定要慎用 blueprint.before_app_request
  • blueprint 层面没有 before_first_request,如果要使用 blueprint.before_app_first_request 等同于 app.before_first_request 了,这个也要慎用。
  • 对于 blueprint.before_app_first_request 的应用场景是在各个 blueprint 中可以单独添加一些自己需要初始化的变量,各个 blueprint 中的这个操作相互是不会覆盖的,只是在 app 层面的 before_first_request 中做“加操作”,避免了直接修改 app.before_first_request 全局型代码在开发管理层面上带来的不便(假如app层面的代码和各个 blueprint 由不同的人维护)

相关文章

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

    在所有请求之前添加钩子 在做验证是否是登陆用户之类的功能时,一定会涉及到与此相关的知识点。 对于直接用 app.a...

  • Flask返回图片

    Flask响应请求有以下几种方法: render_template 返回模板文件 jsonify 返回json格式...

  • flask的路由

    前言 在flask应用中,路由是指用户请求的URL和视图函数之间的映射。flask框架会根据http请求的URL在...

  • 数据分析知识图谱- part1

    在日常分析中,常会遇到不知道选择什么分析方法的尴尬情况出现,尤其是在面对几种相似的方法,不知道它们之间有什么差别,...

  • flask中请求上下文和应用上下文

    请求上下文 在flask 0.9版本之前,flask中只有“请求上下文”的概念。那什么是请求上下文呢? 我们先回忆...

  • laravel下captcha在接口中的使用笔记!

    请求接口获取验证码,验证的时候传递key和img中的字符,调用验证方法验证。

  • iOS网络请求

    一、NSURLConnection NSURLConnection常见的发送请求方法有以下几种 同步请求 异步请求...

  • Day20-flask-login和flask-wtf

    一、表单验证 前言 在Flask项目开发中针对提交表单的校验,可以使用Flask-WTF扩展库进行快速的字段校验,...

  • 基于JWT的接口权限验证

    在做登录界面时,有很多关于安全验证的方法,比如:1、可以使用Session来实现安全验证2、对请求的接口的参数进行...

  • CORS跨域预检查的坑

    跨域预检查的事先请求(Pre-flight Request)会使用OPTIONS方法发送请求,所以在flask中,...

网友评论

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

      本文链接:https://www.haomeiwen.com/subject/lpedextx.html