如何使用字符串(安全地)访问深层Python属性?

时间:2014-04-16 10:32:07

标签: python

我正在尝试找到一种方法来允许我的用户请求Python对象的任意部分,并让服务器返回该数据,而不会意外地允许他们请求他们不允许的内容拥有或做他们不允许做的事情。

例如,假设服务器有这些数据:

my_stuff = {"alpha": ["bravo", "charlie", {"delta": "echo"}], "foxtrot": "golf"}

我想允许用户发送HTTP请求,如:

/path/to/my/script/?gimme=my_stuff[alpha][2][delta]

并让请求返回echo。同样,如果gimme=foxtrot,我想返回golf

我不能把它传递给eval()吗?仅安全问题就是非常糟糕,但我无法想象其性能也非常好。

请求的语法可以完全改变,要求是我允许用户请求服务器端对象的任意部分 ....但是只是那个对象,只读。

有没有安全/聪明的方法来做到这一点,还是我疯了?

1 个答案:

答案 0 :(得分:0)

Martijn Pieters让我走上正轨,但仍有一些工作要弄清楚如何让reduce()遍历各种对象类型,所以我在这里概述所有这些。

对于我的情况,my_stuff实际上是一个具有许多不同属性类型的对象:

class Alpha(object):
    def __init__(self):
        bravo = [1, 2, 3]
        charlie = 7

class Delta(object):
    def __init__(self):
        echo = [Alpha(), Alpha()]
        foxtrot = {
            "golf": "hotel"
        }

reduce(dict.__getitem__, path, my_stuff)那样简单的事情并没有在这里完成工作。尽管如此,我最终得到了这个:

def get_parsed_attribute(self, result, field_name):
    try:
        return reduce(self.smart_getattr, field_name.split("__"), result)
    except (AttributeError, IndexError):
        return None  # We can assume that either the value is missing, or
                     # that key doesn't exist.  Either way, there's no harm.


@staticmethod
def smart_getattr(obj, key):
    if isinstance(obj, list):
        return list.__getitem__(obj, int(key))
    if isinstance(obj, dict):
        return dict.__getitem__(obj, key)
    return getattr(obj, key)

此代码指出我们处理的对象和执行适当的getter的对象,因此当reduce()调用它时,我们得到的结果与我们Martijn为我建议的效果相同简单的字典。