沙箱

jinja2沙盒可用于评估不受信任的代码。禁止访问不安全的属性和方法。

假设 env 是一个 SandboxedEnvironment 在默认配置中,以下代码显示了它的工作方式:

>>> env.from_string("{{ func.func_code }}").render(func=lambda:None)
u''
>>> env.from_string("{{ func.func_code.do_something }}").render(func=lambda:None)
Traceback (most recent call last):
  ...
SecurityError: access to attribute 'func_code' of 'function' object is unsafe.

API

class jinja2.sandbox.SandboxedEnvironment([options])

沙盒环境。它的工作方式与常规环境类似,但它告诉编译器生成沙盒代码。此外,此环境的子类可能会重写那些告诉运行时哪些属性或函数可以安全访问的方法。

如果模板试图访问不安全的代码A SecurityError 提高了。但是,在呈现期间也可能发生其他异常,因此调用方必须确保捕获所有异常。

call_binop(context, operator, left, right)

对于截获的二进制运算符调用 (intercepted_binops() )执行此函数而不是内置运算符。这可以用来微调某些运算符的行为。

2.6 新版功能.

call_unop(context, operator, arg)

对于截获的一元运算符调用 (intercepted_unops() )执行此函数而不是内置运算符。这可以用来微调某些运算符的行为。

2.6 新版功能.

default_binop_table = {'%': <built-in function mod>, '*': <built-in function mul>, '**': <built-in function pow>, '+': <built-in function add>, '-': <built-in function sub>, '/': <built-in function truediv>, '//': <built-in function floordiv>}

二进制运算符的默认回调表。此副本在沙盒环境的每个实例上都可用,如下所示 binop_table

default_unop_table = {'+': <built-in function pos>, '-': <built-in function neg>}

一元运算符的默认回调表。此副本在沙盒环境的每个实例上都可用 unop_table

intercepted_binops = frozenset({})

应该截取的一组二进制运算符。添加到此集合中的每个运算符(默认为空)都委托给 call_binop() 将执行运算符的方法。默认的运算符回调由 binop_table .

以下二进制运算符是可拦截的: //, %, +, *, -, /, and `` **

operator表的默认操作对应于内置函数。截获的调用总是比本机运算符调用慢,因此请确保只截获您感兴趣的调用。

2.6 新版功能.

intercepted_unops = frozenset({})

应截取的一元运算符集。添加到此集合中的每个运算符(默认为空)都委托给 call_unop() 将执行运算符的方法。默认的运算符回调由 unop_table .

以下一元运算符是可拦截的: +-

operator表的默认操作对应于内置函数。截获的调用总是比本机运算符调用慢,因此请确保只截获您感兴趣的调用。

2.6 新版功能.

is_safe_attribute(obj, attr, value)

沙盒环境将调用此方法以检查对象的属性是否可以安全访问。默认情况下,所有以下划线开头的属性都被视为私有属性,以及由 is_internal_attribute() 功能。

is_safe_callable(obj)

检查对象是否可安全调用。默认情况下,函数被认为是安全的,除非 unsafe_callable 属性存在且为真。重写此方法以更改行为,但这不会影响 unsafe 来自此模块的修饰符。

class jinja2.sandbox.ImmutableSandboxedEnvironment([options])

和普通的一样 SandboxedEnvironment 但不允许对内置可变对象进行修改 listsetdict 通过使用 modifies_known_mutable() 功能。

exception jinja2.sandbox.SecurityError(message=None)

如果模板尝试执行不安全的操作(如果启用了沙盒),则引发。

jinja2.sandbox.unsafe(f)

将函数或方法标记为不安全。

@unsafe
def delete(self):
    pass
jinja2.sandbox.is_internal_attribute(obj, attr)

测试给定的属性是否为内部python属性。例如,此函数返回 True 对于 func_code python对象的属性。如果环境方法 is_safe_attribute() 被重写。

>>> from jinja2.sandbox import is_internal_attribute
>>> is_internal_attribute(str, "mro")
True
>>> is_internal_attribute(str, "upper")
False
jinja2.sandbox.modifies_known_mutable(obj, attr)

此函数检查内置可变对象(list、dict、set或deque)上的属性是否会在调用时对其进行修改。它还支持对象的“用户”版本 (sets.SetUserDict.* 等),然后使用python 2.6继续抽象基类 MutableSetMutableMappingMutableSequence .

>>> modifies_known_mutable({}, "clear")
True
>>> modifies_known_mutable({}, "keys")
False
>>> modifies_known_mutable([], "append")
True
>>> modifies_known_mutable([], "index")
False

如果使用不支持的对象(如Unicode)调用 False 返回。

>>> modifies_known_mutable("foo", "upper")
False

注意

Jinja2沙盒本身并不是完美安全的解决方案。尤其是对于Web应用程序,您必须记住,用户可能会在中创建带有任意HTML的模板,因此确保(如果您在同一服务器上运行多个用户)他们不会通过JavaScript插入等方式互相伤害至关重要。

另外,沙盒也只和配置一样好。我们强烈建议只将非共享资源传递给模板,并对属性使用某种白名单。

还要记住,模板可能会引发运行时或编译时错误,因此请确保捕获它们。

运算符拦截

2.6 新版功能.

为了获得最佳性能,jinja2将允许运算符直接调用特定于类型的回调方法。这意味着不可能通过覆盖 Environment.call() . 此外,由于运算符的工作方式,从运算符转换为特殊方法并不总是直接可行的。例如,对于分部,存在多个特殊方法。

使用Jinja 2.6,现在可以支持显式的运算符截取。这可用于根据需要自定义特定的运算符。为了拦截运算符,必须覆盖 SandboxedEnvironment.intercepted_binops 属性。一旦需要截取的运算符添加到该集合中,jinja2将生成调用 SandboxedEnvironment.call_binop() 功能。对于一元运算符 unary 必须改用属性和方法。

默认实现 SandboxedEnvironment.call_binop 将使用 SandboxedEnvironment.binop_table 将运算符符号转换为执行默认运算符行为的回调。

这个例子展示了 (** )运算符可在Jinja2中禁用:

from jinja2.sandbox import SandboxedEnvironment


class MyEnvironment(SandboxedEnvironment):
    intercepted_binops = frozenset(['**'])

    def call_binop(self, context, operator, left, right):
        if operator == '**':
            return self.undefined('the power operator is unavailable')
        return SandboxedEnvironment.call_binop(self, context,
                                               operator, left, right)

确保始终调用super方法,即使您没有截获调用。jinja2可能在内部调用该方法来计算表达式。