Um einige Kontextdaten an Javascript-Code zu übergeben, müssen Sie sie so serialisieren, dass sie von Javascript (nämlich JSON) "verstanden" werden. Sie müssen es auch mit dem safe
Jinja-Filter als sicher markieren , um zu verhindern, dass Ihre Daten htmlescaped werden.
Sie können dies erreichen, indem Sie so etwas tun:
Die Aussicht
import json
@app.route('/')
def my_view():
data = [1, 'foo']
return render_template('index.html', data=json.dumps(data))
Die Vorlage
<script type="text/javascript">
function test_func(data) {
console.log(data);
}
test_func({{ data|safe }})
</script>
Bearbeiten - genaue Antwort
Um genau das zu erreichen, was Sie möchten (eine Liste von Elementen durchlaufen und an eine Javascript-Funktion übergeben), müssen Sie jedes Element in Ihrer Liste separat serialisieren. Ihr Code würde dann so aussehen:
Die Aussicht
import json
@app.route('/')
def my_view():
data = [1, "foo"]
return render_template('index.html', data=map(json.dumps, data))
Die Vorlage
{% for item in data %}
<span onclick=someFunction({{ item|safe }});>{{ item }}</span>
{% endfor %}
Bearbeiten 2
In meinem Beispiel, das ich verwende Flask
, weiß ich nicht, welches Framework Sie verwenden, aber Sie haben die Idee, Sie müssen es nur an das von Ihnen verwendete Framework anpassen.
Bearbeiten 3 (Sicherheitswarnung)
Tun Sie dies niemals mit vom Benutzer bereitgestellten Daten, sondern nur mit vertrauenswürdigen Daten!
Andernfalls würden Sie Ihre Anwendung XSS-Schwachstellen aussetzen!
{{item|tojson|safe}}
stattdessen zu tun" ><script>alert('pwned');</script> "
Sie XSSed. Ja, Sie haben eine Sicherheitswarnung, aber dennoch ist dies eine schlechte Antwort. Es gibt saubere Wege, die nicht kaputt sind (wie die Verwendung des Flask-tojson
Filters), und diese sollten stattdessen verwendet werden.Ich hatte ein ähnliches Problem mit Flask, musste aber nicht auf JSON zurückgreifen. Ich habe gerade eine Liste
letters = ['a','b','c']
mit übergebenrender_template('show_entries.html', letters=letters)
und festgelegtvar letters = {{ letters|safe }}
in meinem Javascript-Code. Jinja2 ersetzt
{{ letters }}
durch['a','b','c']
, das Javascript als Array von Strings interpretiert.quelle
</script><script>alert('pwned')</script>
, wird Ihre Seite beschädigt.Sie können dies mit Jinjas
tojson
Filter tun , derSchreiben Sie beispielsweise in Ihrem Python:
some_template.render(list_of_items=list_of_items)
... oder im Kontext eines Flask-Endpunkts:
return render_template('your_template.html', list_of_items=list_of_items)
Schreiben Sie dann in Ihre Vorlage Folgendes:
{% for item in list_of_items %} <span onclick='somefunction({{item | tojson}})'>{{item}}</span><br> {% endfor %}
(Beachten Sie, dass das
onclick
Attribut ist Single -quoted. Dies da notwendig ist ,|tojson
entkommt'
Zeichen aber nicht"
Zeichen in seinem Ausgang, was bedeutet , dass es sicher in einfachen Anführungszeichen verwendet werden können HTML - Attribute , aber nicht in doppelten Anführungszeichen diejenigen.)Oder
list_of_items
schreiben Sie Folgendes, um es in einem Inline-Skript anstelle eines HTML-Attributs zu verwenden:<script> const jsArrayOfItems = {{list_of_items | tojson}}; // ... do something with jsArrayOfItems in JavaScript ... </script>
Verwenden Sie diese Option NICHT
json.dumps
, um Variablen in Ihrem Python-Code mit JSON zu codieren und den resultierenden JSON-Text an Ihre Vorlage zu übergeben. Dies führt bei einigen Zeichenfolgenwerten zu einer falschen Ausgabe und setzt Sie XSS aus, wenn Sie versuchen, vom Benutzer bereitgestellte Werte zu codieren. Dies liegt daran, dass in Pythons integriertemjson.dumps
Zeichen keine Zeichen wie<
und>
(die maskiert werden müssen, um Werte sicher in Inlines zu speichern)<script>
entfallen, wie unter https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for angegeben -Inhalte-von-Skript-Elementen ) oder einfache Anführungszeichen (die müssen, um Werte sicher in einfache HTML-Attribute mit einfachen Anführungszeichen zu verschieben).Wenn Sie Flask verwenden, beachten Sie, dass Flask
tojson
anstelle der Jinja-Version einen benutzerdefinierten Filter injiziert . Es gilt jedoch weiterhin alles oben Geschriebene. Die beiden Versionen verhalten sich fast identisch; Flask erlaubt nur einige app-spezifische Konfigurationen , die in Jinjas Version nicht verfügbar sind.quelle
Um die ausgewählte Antwort zusammenzufassen, habe ich eine neue Option getestet, die auch mit jinja2 und flask funktioniert:
@app.route('/') def my_view(): data = [1, 2, 3, 4, 5] return render_template('index.html', data=data)
Die Vorlage:
<script> console.log( {{ data | tojson }} ) </script>
die Ausgabe der gerenderten Vorlage:
<script> console.log( [1, 2, 3, 4] ) </script>
Das
safe
könnte hinzugefügt werden, aber auch gerne{{ data | tojson | safe }}
HTML-Escape vermeiden, aber es funktioniert auch ohne.quelle
Ich kann Ihnen einen Javascript-orientierten Ansatz vorschlagen, der es einfach macht, mit Javascript-Dateien in Ihrem Projekt zu arbeiten.
Erstellen Sie einen Javascript-Abschnitt in Ihrer Jinja-Vorlagendatei und platzieren Sie alle Variablen, die Sie in Ihren Javascript-Dateien verwenden möchten, in einem Fensterobjekt:
Start.html
... {% block scripts %} <script type="text/javascript"> window.appConfig = { debug: {% if env == 'development' %}true{% else %}false{% endif %}, facebook_app_id: {{ facebook_app_id }}, accountkit_api_version: '{{ accountkit_api_version }}', csrf_token: '{{ csrf_token }}' } </script> <script type="text/javascript" src="{{ url_for('static', filename='app.js') }}"></script> {% endblock %}
Jinja ersetzt Werte und unser appConfig-Objekt ist über unsere anderen Skriptdateien erreichbar:
App.js.
var AccountKit_OnInteractive = function(){ AccountKit.init({ appId: appConfig.facebook_app_id, debug: appConfig.debug, state: appConfig.csrf_token, version: appConfig.accountkit_api_version }) }
Ich habe Javascript-Code auf diese Weise von HTML-Dokumenten getrennt, was einfacher zu verwalten und seofreundlich ist.
quelle
</script><script>alert("XSSed ur site!!1")</script>
). Die Behauptung in Ihrem letzten Absatz, dass SEO davon beeinflusst wird, ob eine Website Inline-JavaScript oder externe Skripte verwendet, erscheint mir ebenfalls zweifelhaft.<input type="hidden" name="server_data" value="DATA">
Daten sind json-codiert und müssen natürlich maskiert werden. Und die zweite ist eine API-Anfrage. Wenn Ihre Daten vom Besucher abhängen, ist es am besten, sie durch eine API-Anfrage zu erhalten.Erstellen Sie einige unsichtbare HTML-Tags wie
<label>, <p>, <input>
usw. und benennen Sie die ID. Der Klassenname ist ein Muster, damit Sie ihn später abrufen können.Sie haben zwei Listen "tenance_next [] "und" Maintenance_block_time [] "gleicher Länge, und Sie möchten die Daten dieser beiden Listen mithilfe des Kolbens an Javascript übergeben. Sie nehmen also ein unsichtbares Label-Tag und legen fest, dass der Tag-Name ein Muster des Listenindex ist, und legen den Klassennamen als Wert am Index fest.
{% for i in range(maintenance_next|length): %} <label id="maintenance_next_{{i}}" name="{{maintenance_next[i]}}" style="display: none;"></label> <label id="maintenance_block_time_{{i}}" name="{{maintenance_block_time[i]}}" style="display: none;"></label> {% endfor%}
Jetzt können Sie die Daten in Javascript mit einer Javascript-Operation wie unten abrufen -
<script> var total_len = {{ total_len }}; for (var i = 0; i < total_len; i++) { var tm1 = document.getElementById("maintenance_next_" + i).getAttribute("name"); var tm2 = document.getElementById("maintenance_block_time_" + i).getAttribute("name"); //Do what you need to do with tm1 and tm2. console.log(tm1); console.log(tm2); } </script>
quelle