Python Flask 拦截器
拦截器
对接口请求进行预先处理,然后再交由控制器。(中间关卡)
比如用户如果没有登录,则拦截器直接拦截请求,不会将请求转发给控制器。进而实现对接口的权限控制。
在Flask 中,拦截器主要有两种:
全局拦截器
应用于Flask实例(app)中,对所有经过当前系统的请求进行拦截检查。
需要在函数前加上@app.before_request这个装饰器,意为在处理请求前应该做的事情
import os
from flask import Flask, request, session
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) # 生成24位的随机数种子,用于产生SESSION ID
@app.route('/article/<int:article_id>')
def test(article_id):
"""
路由地址参数, 必须同步定义在接口函数里,作为形参
"""
return f'你正在访问编号为:{article_id}的文章'
@app.route('/sess')
def sess():
session['is_login'] = 'true'
return 'done'
@app.before_request
def before():
"""
针对app实例定义全局拦截器
"""
url = request.path # 读取到当前接口的地址
if url == '/sess':
pass
elif session.get('is_login', '') != 'true':
return '你还没有登录'
else:
pass
if '__name__' == '__main__':
app.run()
这个时候,无论该网站的什么地址,只要不是is_login == 'true',请求就会被事先拦截
想进去,必须先 '登录' ,得到这个session
接着之前的访问,成功了
可是这样的拦截器有很多缺点:
-
需要制定白名单
-
因为拦截器作用在全局,那么所有的网页,静态资源,js一概会被拦截,导致有些必要网页根本加载不出来
-
有了白名单就可以保证哪些网页和资源可以正常加载,定制白名单是比较麻烦的,后期可能还会不断修改它
拦截器函数可能要这样写
@app.before_request def before(): """ 针对app实例定义全局拦截器 """ url = request.path # 读取到当前接口的地址 pass_list = ['/', 'reg', 'login', 'sess'] suffix = url.endswith('.png') or url.endswith('.jpg') or url.endswith('.css') or url.endswith('.js') if url in pass_list or suffix: pass elif session.get('is_login') != 'true': return '你还没有登录' else: pass
-
-
降低了服务器的性能
- 要对每个接口都进行拦截器预先判断
模块拦截器
也叫视图拦截器,只针对某一个模块进行拦截,应用于Blueprint模块中。
把需要事前拦截的接口和拦截器一起放在一个视图模板里
controller/auth.py
from flask import Blueprint, session
auth = Blueprint('auth', __name__)
@auth.route('/article/<int:article_id>')
def article(article_id):
"""
路由地址参数, 必须同步定义在接口函数里,作为形参
"""
return f'你正在访问编号为:{article_id}的文章'
@auth.before_request
def before():
if session.get('is_login') != 'true':
return '你还没有登录'
else:
pass
main.py
import os
from flask import Flask, request, session
from controller.auth import auth
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24) # 生成24位的随机数种子,用于产生SESSION ID
app.register_blueprint(auth)
@app.route('/sess')
def sess():
session['is_login'] = 'true'
return 'done'
if '__name__' == '__main__':
app.run()
可以看到,只有设置了拦截器的接口是访问不了的,其他的页面包括图片,css,js等都能成功加载并渲染
接着得先获取session,才能成功访问接口
全局拦截器在需要控制极其隐私的地方可以使用,比如网站的后台管理接口等,其他的地方不推荐使用
模块拦截器把很多不同功能的拦截器分开来,模块化。将权限分成好几个等级,不同等级可以访问不同的接口,是安全高效的