Песочница
Песочница Jinja может использоваться для рендеринга недоверенных шаблонов. Доступ к атрибутам, вызовам методов, операторам, изменению структур данных и форматированию строк может быть перехвачен и запрещен.
>>> from jinja2.sandbox import SandboxedEnvironment
>>> env = SandboxedEnvironment()
>>> func = lambda: "Hello, Sandbox!"
>>> env.from_string("{{ func() }}").render(func=func)
'Hello, Sandbox!'
>>> env.from_string("{{ func.__code__.co_code }}").render(func=func)
Traceback (most recent call last):
...
SecurityError: access to attribute '__code__' of 'function' object is unsafe.
Песочница полезна, например, для того, чтобы пользователи внутренней системы отчетов могли создавать пользовательские письма. Вы бы документировали, какие данные доступны в шаблонах, а затем пользователь писал бы шаблон, используя эту информацию. Ваш код генерировал бы данные отчета и передавал бы их в песочницу пользователя для рендеринга.
Соображения безопасности
Сама песочница не является решением для идеальной безопасности. Имейте в виду эти моменты, когда используете песочницу.
Шаблоны по-прежнему могут генерировать ошибки при компиляции или рендеринге. Ваш код должен пытаться перехватывать ошибки, а не вызывать сбой.
Возможно создание относительно небольшого шаблона, который генерирует очень большое количество вывода, что может привести к высокому использованию ЦП или памяти. Вы должны запускать свою программу с ограничениями на ресурсы, такие как ЦП и память, чтобы смягчить это.
Jinja рендерит только текст, он не понимает, например, код JavaScript. В зависимости от того, как будет использоваться рендеренный шаблон, вам может потребоваться выполнить дополнительную пост-обработку для ограничения вывода.
Передавайте только данные, относящиеся к шаблону. Избегайте передачи глобальных данных или объектов с методами, имеющими побочные эффекты. По умолчанию песочница предотвращает доступ к приватным и внутренним атрибутам. Вы можете переопределить is_safe_attribute() для дальнейшего ограничения доступа к атрибутам. Декорируйте методы unsafe(), чтобы предотвратить их вызов из шаблонов при передаче объектов в качестве данных. Используйте ImmutableSandboxedEnvironment, чтобы предотвратить изменение списков и словарей.
API
-
class jinja2.sandbox.SandboxedEnvironment([options]) -
Песочница окружения. Оно работает как обычное окружение, но сообщает компилятору сгенерировать песочницу. Кроме того, подклассы этого окружения могут переопределять методы, которые сообщают исполняемому модулю, какие атрибуты или функции безопасно обработать.
Если шаблон пытается получить доступ к небезопасным данным, поднимается
SecurityError. Однако во время рендеринга могут возникнуть и другие исключения, поэтому вызывающий код должен гарантировать, что все исключения перехвачены.-
call_binop(context, operator, left, right) -
Для перехваченных бинарных операторов (
intercepted_binops()) эта функция выполняется вместо встроенного оператора. Это можно использовать для настройки поведения определенных операторов.Changelog
Новое в версии 2.6.
-
call_unop(context, operator, arg) -
Для перехваченных унарных операторов (
intercepted_unops()) эта функция выполняется вместо встроенного оператора. Это можно использовать для настройки поведения определенных операторов.Changelog
Новое в версии 2.6.
-
default_binop_table: Dict[str, Callable[[Any, Any], Any]] = {'%': <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: Dict[str, Callable[[Any], Any]] = {'+': <built-in function pos>, '-': <built-in function neg>} -
Таблица обратных вызовов для унарных операторов по умолчанию. Копия доступна в каждом экземпляре песочницы как
unop_table
-
-
intercepted_binops: FrozenSet[str] = frozenset({}) -
набор бинарных операторов, которые должны быть перехвачены. Каждый оператор, добавленный в этот набор (по умолчанию пустой), делегируется методу
call_binop(), который выполнит оператор. Обработчик оператора по умолчанию задаётсяbinop_table.Следующие бинарные операторы могут быть перехвачены:
//,%,+,*,-,/, и**По умолчанию операция из таблицы операторов соответствует встроенной функции. Перехваченные вызовы всегда медленнее, чем вызовы нативных операторов, поэтому убедитесь, что перехватываете только интересующие вас операторы.
Изменения
Введено в версии 2.6.
-
intercepted_unops: FrozenSet[str] = frozenset({}) -
набор унарных операторов, которые должны быть перехвачены. Каждый оператор, добавленный в этот набор (по умолчанию пустой), делегируется методу
call_unop(), который выполнит оператор. Обработчик оператора по умолчанию задаётсяunop_table.Следующие унарные операторы могут быть перехвачены:
+,-По умолчанию операция из таблицы операторов соответствует встроенной функции. Перехваченные вызовы всегда медленнее, чем вызовы нативных операторов, поэтому убедитесь, что перехватываете только интересующие вас операторы.
Изменения
Введено в версии 2.6.
-
is_safe_attribute(obj, attr, value) -
Sandboxed среда вызовет этот метод для проверки, безопасно ли получить атрибут объекта. По умолчанию все атрибуты, начинающиеся с нижнего подчёркивания, считаются закрытыми, а также специальные атрибуты внутренних объектов Python, возвращаемые функцией
is_internal_attribute().
-
is_safe_callable(obj) -
Проверка, является ли объект безопасным вызываемым объектом. По умолчанию вызываемые объекты считаются безопасными, если они не помечены декоратором
unsafe().Также распознаётся соглашение Django о настройке
func.alters_data = True.
-
class jinja2.sandbox.ImmutableSandboxedEnvironment([options]) -
Поведение идентично обычному
SandboxedEnvironment, но запрещает модификации встроенных изменяемых объектовlist,set, иdict, используя функциюmodifies_known_mutable().
-
-
exception jinja2.sandbox.SecurityError(message=None) -
Возникает, если шаблон пытается выполнить небезопасное действие, если режим песочницы включен.
- Параметры:
-
message (str | None) –
- Тип возвращаемого значения:
-
None
-
jinja2.sandbox.unsafe(f) -
Помечает функцию или метод как небезопасный.
- Параметры:
-
f (F) –
- Тип возвращаемого значения:
-
F
-
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) -
Эта функция проверяет, будет ли вызов атрибута изменяемого встроенного объекта (списка, словаря, множества или очереди) или соответствующих ABC изменять его.
>>> modifies_known_mutable({}, "clear") True >>> modifies_known_mutable({}, "keys") False >>> modifies_known_mutable([], "append") True >>> modifies_known_mutable([], "index") FalseЕсли вызывается с неподдерживаемым объектом, возвращается
False.>>> modifies_known_mutable("foo", "upper") False
Перехват операторов
Для повышения производительности Jinja выводит операторы напрямую при компиляции. Это означает, что по умолчанию перехватить поведение оператора путём переопределения SandboxEnvironment.call невозможно, так как специальные методы операторов обрабатываются интерпретатором Python и могут не соответствовать точно одному методу в зависимости от использования оператора.
Режим песочницы может указать компилятору выводить функцию для перехвата определенных операторов. Переопределите SandboxedEnvironment.intercepted_binops и SandboxedEnvironment.intercepted_unops символами операторов, которые вы хотите перехватить. Компилятор заменит символы вызовами SandboxedEnvironment.call_binop() и SandboxedEnvironment.call_unop() соответственно. По умолчанию эти методы будут использовать SandboxedEnvironment.binop_table и SandboxedEnvironment.unop_table для перевода символов операторов в функции operator.
Например, оператор возведения в степень (**) можно отключить:
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 super().call_binop(self, context, operator, left, right)
© 2007–2021 Pallets
Licensed under the BSD 3-clause License.
https://jinja.palletsprojects.com/en/3.1.x/sandbox/