python Flask 装饰器顺序问题解决


Posted in Python onAugust 08, 2018

上周 RealWorld CTF 2018 web 题 bookhub 有个未授权访问的漏洞,比较有意思,赛后看了一下公开的 WriteUp,大家也都没写清楚,所以就有了这篇博文。

前言

这个题是用 flask 框架写的,在 www/bookhub/views/user.py 中, refresh_session 方法存在未授权访问漏洞,代码是这样写的:

@login_required
@user_blueprint.route('/admin/system/refresh_session/', methods=['POST'])
def refresh_session():
 pass # 这里省略内容

注意看 @login_required 这个装饰器写在了 route 装饰器上面了,导致了 login_required 未调用。那么,为什么会这样子呢?

官方文档

Flask 官方文档中关于Login Required Decorator说明 这一节里面有一行说明:

To use the decorator, apply it as innermost decorator to a view function. When applying further decorators, always remember that the route() decorator is the outermost.

大概意思就是,必须保证 route 装饰器在最顶层

那么为什么要这样提示呢?

Python 装饰器顺序说明

本节内容可直接参考: Python 装饰器执行顺序迷思

总结一下就是,装饰的顺序按靠近函数顺序执行,从内到外装饰,调用时由外而内,执行顺序和装饰顺序相反。

回过头来看 Flask

Flask 框架中, route 装饰器是这么写的:

def route(self, rule, **options):
 """Like :meth:`Flask.route` but for a blueprint. The endpoint for the
 :func:`url_for` function is prefixed with the name of the blueprint.
 """
 def decorator(f):
  endpoint = options.pop("endpoint", f.__name__)
  self.add_url_rule(rule, endpoint, f, **options)
  return f
 return decorator

route 调用了 add_url_rule , 对传入的 f 添加一条 URL 规则。

所以,按照 python 装饰器顺序:

  1. 如果 @app.route 在内层,那么就会把最原始的 view 函数传给 add_url_rule , Flask 框架就会添加一条 URL 规则,指向最原始的 view 函数。
  2. 如果 @app.route 在外层,那么就会把已经被 login_required 装饰过的 view 函数传给 add_url_rule , Flask 框架就会添加一条 URL 规则,指向已经装饰过的 view 函数。

下面是两个例子,来说明:

正确写法

@user_blueprint.route('/admin/refresh_session/', methods=['POST'])
@login_required
def refresh_session():
 pass

这段代码相当于:

# 这里没有装饰器
def refresh_session():
 pass

login_wrapped = login_required(refresh_session) # login 装饰器
both_wrapped = app.route('/admin/refresh_session/')(login_wrapped) # route 装饰器

/admin/refresh_session/ 这条路由指向的实际是 login_wrapped ,这样就会经过 login 检查

错误写法

@login_required
@user_blueprint.route('/admin/refresh_session/', methods=['POST'])
def refresh_session():
 pass

这段代码相当于:

# 这里没有装饰器
def refresh_session():
 pass

route_wrapped = app.route('/admin/refresh_session/')(refresh_session) # route 装饰器
login_wrapped = login_required(route_wrapped)  # login 装饰器

/admin/refresh_session/ 这条路由指向的实际是 refresh_session , 而 login_wrapped 并没有与路由挂勾,所以不会被调用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3中的真除和Floor除法用法分析
Mar 16 Python
轻松掌握python设计模式之访问者模式
Nov 18 Python
Python图像滤波处理操作示例【基于ImageFilter类】
Jan 03 Python
Python JSON格式数据的提取和保存的实现
Mar 22 Python
pyqt 多窗口之间的相互调用方法
Jun 19 Python
Python分析彩票记录并预测中奖号码过程详解
Jul 09 Python
对Django中static(静态)文件详解以及{% static %}标签的使用方法
Jul 28 Python
Python Django 简单分页的实现代码解析
Aug 21 Python
在flask中使用python-dotenv+flask-cli自定义命令(推荐)
Jan 05 Python
Python如何向SQLServer存储二进制图片
Jun 08 Python
Python爬虫爬取微信朋友圈
Aug 06 Python
利用python汇总统计多张Excel
Sep 22 Python
Python BS4库的安装与使用详解
Aug 08 #Python
python特性语法之遍历、公共方法、引用
Aug 08 #Python
用Python shell简化开发
Aug 08 #Python
在Python中使用gRPC的方法示例
Aug 08 #Python
Python实现购物评论文本情感分析操作【基于中文文本挖掘库snownlp】
Aug 07 #Python
python实现彩票系统
Jun 28 #Python
django框架自定义用户表操作示例
Aug 07 #Python
You might like
PHP 7的一些引人注目的新特性简单介绍
2015/11/08 PHP
微信公众平台DEMO(PHP)
2016/05/04 PHP
php DES加密算法实例分析
2019/09/18 PHP
初试jQuery EasyUI 使用介绍
2010/04/01 Javascript
分享14个很酷的jQuery导航菜单插件
2011/04/25 Javascript
Javascript的严格模式strict mode详细介绍
2014/06/06 Javascript
基于jquery实现的树形菜单效果代码
2015/09/06 Javascript
Bootstrap的popover(弹出框)2秒后定时消失的实现代码
2017/02/27 Javascript
@ResponseBody 和 @RequestBody 注解的区别
2017/03/08 Javascript
原生js实现密码输入框值的显示隐藏
2017/07/17 Javascript
简述JS控制台的使用
2018/07/15 Javascript
解决LayUI表单获取不到data的问题
2018/08/20 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
微信公众号服务器验证Token步骤图解
2019/12/30 Javascript
JavaScript实现简单计算器
2020/03/19 Javascript
[15:56]Heroes18_暗影萨满(完美)
2014/10/31 DOTA
[01:20]辉夜杯背景故事宣传片《辉夜传说》
2015/12/25 DOTA
Python数据类型学习笔记
2016/01/13 Python
pandas使用get_dummies进行one-hot编码的方法
2018/07/10 Python
Python 读取串口数据,动态绘图的示例
2019/07/02 Python
python求一个字符串的所有排列的实现方法
2020/02/04 Python
用python介绍4种常用的单链表翻转的方法小结
2020/02/24 Python
Currentbody西班牙:美容仪专家
2019/09/28 全球购物
PHP如何对用户密码进行加密
2014/07/31 面试题
三年级语文教学反思
2014/02/01 职场文书
自荐信如何制作?
2014/02/21 职场文书
个性车贴标语
2014/06/24 职场文书
老公给老婆的检讨书(精华篇)
2014/10/18 职场文书
2015年扫黄打非工作总结
2015/05/13 职场文书
军事理论课感想
2015/08/11 职场文书
财务会计个人原因辞职信
2019/06/21 职场文书
导游词之广州陈家祠
2019/10/21 职场文书
CSS3 实现NES游戏机的示例代码
2021/04/21 HTML / CSS
js Proxy的原理详解
2021/05/25 Javascript
Python如何识别银行卡卡号?
2021/06/10 Python
《地。-关于地球的运动-》单行本第七集上市,小说家朝井辽献上期待又害怕的推荐文
2022/03/31 日漫