Подтвердить что ты не робот

Исключить строки для JavaScript с помощью Jinja2?

Как я могу избежать HTML с Jinja2, чтобы он мог использоваться как строка в JavaScript (jQuery)?

Если бы я использовал систему шаблонов Django, я мог бы написать:

$("#mydiv").append("{{ html_string|escapejs }}");

Django |escapejs filter мог бы избежать вещей в html_string (например, кавычки, специальные символы), которые могли бы прервать предполагаемое использование этого блок кода, но Jinja2, похоже, не имеет эквивалентного фильтра (я здесь не прав?).

Есть ли более чистое решение, чем копирование/вставка кода из Django?

4b9b3361

Ответ 1

В прошлом году я столкнулся с аналогичной проблемой. Не уверен, используете ли вы bottle, но мое решение выглядело примерно так.

import json

def escapejs(val):
    return json.dumps(str(val)) # *but see [Important Note] below to be safe

@app.route('/foo')
def foo():
    return bottle.jinja2_template('foo', template_settings={'filters': {'escapejs': escapejs}})

(я обернул template_settings dict в вспомогательную функцию, так как использовал его всюду, но в этом примере я оставил его простым.)

К сожалению, это не так просто, как встроенный фильтр jinja2, но я смог жить с ним счастливо - особенно учитывая, что у меня было еще несколько настраиваемых фильтров.

Важное примечание: подсказка о шляпе к @medmunds для его проницательного комментария ниже, напоминая нам, что json.dumps не является XSS-безопасным. IOW, вы не захотите использовать его на сервере производства, ориентированном на Интернет. Рекомендация - написать безопасную процедуру json escape (или украсть django's - извините OP, я знаю, что вы надеялись избежать этого) и назовите это вместо использования json.dumps.

Ответ 2

Это фильтр escapejs, основанный на Django one, который я написал для использования в шаблонах Jinja2:

_js_escapes = {
        '\\': '\\u005C',
        '\'': '\\u0027',
        '"': '\\u0022',
        '>': '\\u003E',
        '<': '\\u003C',
        '&': '\\u0026',
        '=': '\\u003D',
        '-': '\\u002D',
        ';': '\\u003B',
        u'\u2028': '\\u2028',
        u'\u2029': '\\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in xrange(32))
def jinja2_escapejs_filter(value):
        retval = []
        for letter in value:
                if _js_escapes.has_key(letter):
                        retval.append(_js_escapes[letter])
                else:
                        retval.append(letter)

        return jinja2.Markup("".join(retval))
JINJA_ENVIRONMENT.filters['escapejs'] = jinja2_escapejs_filter

Пример безопасного использования в шаблоне:

<script type="text/javascript">
<!--
var variableName = "{{ variableName | escapejs }}";
…
//-->
</script>

Если variableName является str или unicode.

Ответ 3

У Jinja2 есть хороший фильтр Тойсон. Если вы сделаете json из строки, он сгенерирует строку, заключенную в двойные кавычки "". Вы можете смело использовать его в JavaScript. И вам не нужно помещать цитаты в одиночку.

$("#mydiv").append({{ html_string|tojson }});

Ответ 4

Я только что изучил эту проблему, мое решение - определить фильтр:

from flask import Flask, Markup
app = Flask(__name__)
app.jinja_env.filters['json'] = lambda v: Markup(json.dumps(v))

и в шаблоне:

<script>
var myvar = {{myvar|json}} ;
</script>

Это хорошая функция, что myvar может быть любым, что может быть JSON-сериализованным

Ответ 5

Основываясь на @tometzky, вот моя версия Python 3:

_js_escapes = {
        '\\': '\\u005C',
        '\'': '\\u0027',
        '"': '\\u0022',
        '>': '\\u003E',
        '<': '\\u003C',
        '&': '\\u0026',
        '=': '\\u003D',
        '-': '\\u002D',
        ';': '\\u003B',
        u'\u2028': '\\u2028',
        u'\u2029': '\\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in range(32))

@register.filter
def escapejs(value):
    return jinja2.Markup("".join(_js_escapes.get(l, l) for l in value))

Использование точно так же.

Ответ 6

Вы также можете использовать jinja2 autoescape. Так, например, вы можете добавить autoescape в среду jinja2 в Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    autoescape=True)

В качестве альтернативы вы можете использовать расширение Autoescape, добавленное в Jinja 2.4, чтобы иметь больше контроля над тем, где в HTML используется автоматическое кэширование. Более подробную информацию об этом здесь и пример (в Google App Engine) здесь.

Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'])

HTML:

{% autoescape true %}
    <html>
        <body>
            {{ IWillBeEscaped }}
        </body>
    </html>
{% endautoescape %}