gpt4 book ai didi

python - 如何正确地将参数从 Bottle View 传递到装饰 View ?

转载 作者:太空宇宙 更新时间:2023-11-04 05:14:42 24 4
gpt4 key购买 nike

我想用 CSRF token 保护我的 View ,我采用的方法如下:

from functools import partial
from bottle import jinja2_template as template,

def generate_csrf_token(length):
'''Generate a random string using range [a-zA-Z0-9].'''
chars = string.ascii_letters + string.digits
return ''.join([choice(chars) for i in range(length)])


def require_csrf(callback, *args, **kwargs):
def wrapper(*args, **kwargs):
token = request.params.csrf_token
if not token or token != global_vars['csrf_token']:
abort(400)
body = callback(*args, **kwargs)
return body

return wrapper

global_vars = {'BCC_VERSION': pkg_resources.get_distribution('bcc').version,
'csrf_token': generate_csrf_token(48)}

j2template = partial(template, template_settings={'globals': global_vars})

@app.get("/remove/")
@require_csrf
def remove_device():
ans = {'status': 200,
'body': "csrf_token is: {}".format(global_vars['csrf_token'])}
return HTTPResponse(**ans)

只要 View 不需要任何参数,这就可以正常工作。如果 View 接受数据库连接(例如使用插件时),事情就会变得棘手:

@app.get("/delete/")
@require_csrf
def delete_device(db): # This causes the require_csrf decorator to fail
ans = {'status': 200,
'body': "csrf_token is: {}".format(global_vars['csrf_token'])}
return HTTPResponse(**ans)

访问 /delete/ 时出现以下异常:

Traceback (most recent call last):
File "/home/oznt/.virtualenvs/bcc/lib/python3.4/site-packages/bottle.py", line 979, in _handle
out = route.call(**args)
File "/home/oznt/.virtualenvs/bcc/lib/python3.4/site-packages/bottle.py", line 1949, in wrapper
rv = callback(*a, **ka)
File "/home/oznt/Software/bcc/bcc/views.py", line 32, in wrapper
body = callback(*args, **kwargs)
TypeError: delete_device() missing 1 required positional argument: 'db'

为了解决这个问题,我将 require_csrf 装饰器稍微修改为:

def require_csrf(callback, *args, **kwargs):
import inspect
callback_args = inspect.getargspec(callback)[0]

def wrapper(*args, **kwargs):
token = request.params.csrf_token
if not token or token != global_vars['csrf_token']:
abort(400)
body = callback(*callback_args, **kwargs)
return body

return wrapper

现在一切都按预期进行。但是,我不确定这是解决此问题的正确方法。您能否对此发表评论或针对该问题提出更好的解决方案?

更新

我尝试了世界末日的建议,但出现以下错误:

python3 main.py
Traceback (most recent call last):
File "main.py", line 8, in <module>
from bcc.views import app as home_app
File "/home/oznt/Software/controller_configuration/bcc/views.py", line 66, in <module>
@require_csrf()
TypeError: 'NoneType' object is not callable

最佳答案

您在这里缺少一层函数包装器。下面的代码在没有任何 inspect hack 的情况下工作。

def require_csrf():
def decorator(callback):
def wrapper(*args, **kwargs):
token = request.params.csrf_token
if not token or token != global_vars['csrf_token']:
abort(400)
return callback(*args, **kwargs)
return wrapper
return decorator

@app.get("/remove/<id>")
@require_csrf()
def remove_device(id):
ans = {'status': 200,
'body': "csrf_token is: {}".format(global_vars['csrf_token'])}
return HTTPResponse(**ans)

另请注意,如果需要,您可以向 require_csrf 装饰器和函数添加参数。

关于python - 如何正确地将参数从 Bottle View 传递到装饰 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42068410/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com