鍍金池/ 教程/ Python/ 沙箱
提示和技巧
從其它的模板引擎切換
集成
沙箱
擴(kuò)展
常見問題
介紹
模板設(shè)計(jì)者文檔
API

沙箱

Jinja2 沙箱用于為不信任的代碼求值。訪問不安全的屬性和方法是被禁止的。

假定在默認(rèn)配置中 env 是一個(gè) SandboxedEnvironment 實(shí)例,下面的代碼展示 了它如何工作:

    >>> 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])

The sandboxed environment. It works like the regular environment but tells the compiler to generate sandboxed code. Additionally subclasses of this environment may override the methods that tell the runtime what attributes or functions are safe to access.

If the template tries to access insecure code a SecurityError is raised. However also other exceptions may occour during the rendering so the caller has to ensure that all exceptions are catched.

call_binop(context, operator, left, right)

For intercepted binary operator calls (intercepted_binops()) this function is executed instead of the builtin operator. This can be used to fine tune the behavior of certain operators.

call_unop(context, operator, arg)

For intercepted unary operator calls (intercepted_unops()) this function is executed instead of the builtin operator. This can be used to fine tune the behavior of certain operators.

default_binop_table = {'//': , '%': , '+': , '*': , '-': , '/': , '**': }

default callback table for the binary operators. A copy of this is available on each instance of a sandboxed environment as binop_table

default_unop_table = {'+': , '-': }

default callback table for the unary operators. A copy of this is available on each instance of a sandboxed environment as unop_table

intercepted_binops = frozenset([])

a set of binary operators that should be intercepted. Each operator that is added to this set (empty by default) is delegated to the call_binop() method that will perform the operator. The default operator callback is specified by binop_table.

The following binary operators are interceptable: //, %, +, *, -, /, and **

The default operation form the operator table corresponds to the builtin function. Intercepted calls are always slower than the native operator call, so make sure only to intercept the ones you are interested in.

intercepted_unops = frozenset([])

a set of unary operators that should be intercepted. Each operator that is added to this set (empty by default) is delegated to the call_unop() method that will perform the operator. The default operator callback is specified by unop_table.

The following unary operators are interceptable: +, -

The default operation form the operator table corresponds to the builtin function. Intercepted calls are always slower than the native operator call, so make sure only to intercept the ones you are interested in.

is_safe_attribute(obj, attr, value)

The sandboxed environment will call this method to check if the attribute of an object is safe to access. Per default all attributes starting with an underscore are considered private as well as the special attributes of internal python objects as returned by the is_internal_attribute() function.

is_safe_callable(obj)

Check if an object is safely callable. Per default a function is considered safe unless the unsafe_callable attribute exists and is True. Override this method to alter the behavior, but this won't affect the unsafe decorator from this module.

class jinja2.sandbox.``ImmutableSandboxedEnvironment([options])

Works exactly like the regular SandboxedEnvironment but does not permit modifications on the builtin mutable objects list, set, and dict by using the modifies_known_mutable() function.

exception jinja2.sandbox.``SecurityError(message=None)

Raised if a template tries to do something insecure if the sandbox is enabled.

jinja2.sandbox.``unsafe(f)

Marks a function or method as unsafe.

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

Test if the attribute given is an internal python attribute. For example this function returns True for the func_code attribute of python objects. This is useful if the environment method is_safe_attribute() is overridden.

    >>> from jinja2.sandbox import is_internal_attribute
    >>> is_internal_attribute(lambda: None, "func_code")
    True
    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
    True
    >>> is_internal_attribute(str, "upper")
    False
jinja2.sandbox.``modifies_known_mutable(obj, attr)

This function checks if an attribute on a builtin mutable object (list, dict, set or deque) would modify it if called. It also supports the "user"-versions of the objects (sets.Set, UserDict.* etc.) and with Python 2.6 onwards the abstract base classes MutableSet, MutableMapping, and MutableSequence.

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

If called with an unsupported object (such as unicode) False is returned.

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

提示

Jinja2 沙箱自己并沒有徹底解決安全問題。特別是對 web 應(yīng)用,你必須曉得用戶 可能用任意 HTML 來創(chuàng)建模板,所以保證他們不通過注入 JavaScript 或其它更多 方法來互相損害至關(guān)重要(如果你在同一個(gè)服務(wù) 器上運(yùn)行多用戶)。

同樣,沙箱的好處取決于配置。我們強(qiáng)烈建議只向模板傳遞非共享資源,并 且使用某種屬性白名單。

也請記住,模板會(huì)拋出運(yùn)行時(shí)或編譯期錯(cuò)誤,確保捕獲它們。

運(yùn)算符攔截

為了性能最大化, Jinja2 會(huì)讓運(yùn)算符直接條用類型特定的回調(diào)方法。這意味著, 通過重載 Environment.call() 來攔截是不可能的。此外,由于運(yùn)算符的工作 方式,把運(yùn)算符轉(zhuǎn)換為特殊方法不總是直接可行的。比如為了分類,至少一個(gè)特殊 方法存在。

在 Jinja 2.6 中,開始支持顯式的運(yùn)算符攔截。必要時(shí)也可以用于自定義的特定 運(yùn)算符。為了攔截運(yùn)算符,需要覆寫 SandboxedEnvironment.intercepted_binops 屬性。當(dāng)需要攔截的運(yùn)算符 被添加到這個(gè)集合, Jinja2 會(huì)生成調(diào)用 SandboxedEnvironment.call_binop() 函數(shù)的字節(jié)碼。對于一元運(yùn)算符, 必須替代地使用 unary 屬性和方法。

SandboxedEnvironment.call_binop 的默認(rèn)實(shí)現(xiàn)會(huì)使用 SandboxedEnvironment.binop_table 來把運(yùn)算符標(biāo)號翻譯成執(zhí)行默認(rèn) 運(yùn)算符行為的回調(diào)。

這個(gè)例子展示了冪( ** )操作符可以在 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)

確保始終調(diào)入 super 方法,即使你不攔截這個(gè)調(diào)用。 Jinja2 內(nèi)部會(huì)調(diào)用 這個(gè)方法來對表達(dá)式求值。

上一篇:提示和技巧下一篇:集成