Escape strings for JavaScript using Jinja2?

前端 未结 6 2213
清酒与你
清酒与你 2021-02-18 14:10

How do I escape HTML with Jinja2 so that it can be used as a string in JavaScript (jQuery)?

If I were using Django\'s templating system I could write:

$(         


        
相关标签:
6条回答
  • 2021-02-18 14:46

    I just researched this problem, my solution is to define a filter:

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

    and in the template:

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

    This has the nice feature that myvar can be anything that can be JSON-serialised

    0 讨论(0)
  • 2021-02-18 14:48

    Based on @tometzky here is my Python 3 version:

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

    The usage is exactly the same.

    0 讨论(0)
  • 2021-02-18 14:54

    I faced a similar problem last year. Not sure whether you're using bottle, but my solution looked something like this.

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

    (I wrapped the template_settings dict in a helper function since I used it everywhere, but I kept it simple in this example.)

    Unfortunately, it's not as simple as a builtin jinja2 filter, but I was able to live with it happily--especially considering that I had several other custom filters to add, too.

    Important Note: Hat tip to @medmunds's for his astute comment below, reminding us that json.dumps is not XSS-safe. IOW, you wouldn't want to use it in a production, internet-facing server. Recommendation is to write a safer json escape routine (or steal django's--sorry OP, I know you were hoping to avoid that) and call that instead of using json.dumps.

    0 讨论(0)
  • 2021-02-18 15:07

    You can also use jinja2's autoescape. So, for instance, you could add autoescape to your jinja2 Environment in Python:

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

    Alternatively, you could use the Autoescape Extension added in Jinja 2.4 to have more control over where the autoescaping is used in the HTML. More information on this here and example (in Google App Engine) here.

    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 %}
    
    0 讨论(0)
  • 2021-02-18 15:08

    Jinja2 has nice filter tojson. If you make json from string, it will generate string enclosed in double quotes "". You can safely use it in javascript. And you don't need put quotes around by yourself.

    $("#mydiv").append({{ html_string|tojson }});
    
    0 讨论(0)
  • 2021-02-18 15:09

    This is a escapejs filter, based on Django's one, that I wrote for use in Jinja2 templates:

    _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
    

    Example safe usage in a template:

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

    When variableName is a str or unicode.

    0 讨论(0)
提交回复
热议问题