22

Jinja2でHTMLをエスケープして、JavaScript(jQuery)で文字列として使用できるようにするにはどうすればよいですか?

Djangoのテンプレートシステムを使用している場合、次のように書くことができます。

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

Djangoの|escapejsフィルターは、このコードブロックの使用目的を壊す可能性のあるもの(引用符、特殊文字など)をエスケープしhtml_stringますが、Jinja2には同等のフィルターがないようです(ここで間違っていますか?)。

Djangoからコードをコピー/貼り付けするよりもクリーンな解決策はありますか?

4

6 に答える 6

19

Jinja2には素晴らしいフィルターtojsonがあります。文字列からjsonを作成すると、二重引用符""で囲まれた文字列が生成されます。javascriptで安全に使用できます。また、自分で引用符を付ける必要はありません。

$("#mydiv").append({{ html_string|tojson }});
于 2018-11-18T07:20:20.297 に答える
15

これは、escapejsJinja2テンプレートで使用するために作成したDjangoのフィルターに基づくフィルターです。

_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がastrまたはの場合unicode

于 2013-09-19T17:07:29.080 に答える
9

昨年も同様の問題に直面しました。ボトルを使用しているかどうかはわかりませんが、私のソリューションは次のようになりました。

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(辞書はどこでも使用したのでヘルパー関数でラップしましたが、この例では単純にしています。)

残念ながら、組み込みのjinja2フィルターほど単純ではありませんが、特に他にもいくつかのカスタムフィルターを追加する必要があることを考えると、これを使って幸せに暮らすことができました。

重要な注意:以下の@medmundsの鋭いコメントに対するヒント。json.dumpsはXSSセーフではないことを思い出してください。IOW、インターネットに接続された本番サーバーでは使用したくないでしょう。より安全なjsonエスケープルーチンを作成し(またはdjangoを盗む-申し訳ありませんが、OPを盗むことをお勧めします)、json.dumpsを使用する代わりにそれを呼び出すことをお勧めします。

于 2012-09-09T14:40:09.010 に答える
1

私はこの問題を調査しました。私の解決策はフィルターを定義することです。

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シリアル化できるものなら何でもかまいませんという優れた機能があります

于 2013-10-09T10:11:12.897 に答える
0

@tometzkyに基づいて、ここに私のPython3バージョンがあります。

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

使い方はまったく同じです。

于 2019-06-27T14:11:09.160 に答える
-1

jinja2も使用できますautoescape。したがって、たとえば、Pythonでjinja2環境に自動エスケープを追加できます。

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

または、Jinja 2.4で追加されたAutoescape拡張機能を使用して、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 %}
于 2013-07-06T23:05:05.123 に答える