Kurzfassung!
import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)
# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)
Regex-Quelle: MarkupSafe . Ihre Version verarbeitet auch HTML-Entitäten, während diese schnelle dies nicht tut.
Warum kann ich die Tags nicht einfach entfernen und lassen?
Es ist eine Sache, Menschen von <i>italicizing</i>
Dingen fernzuhalten , ohne dass sie i
herumschweben. Aber es ist eine andere Sache, willkürliche Eingaben zu machen und sie völlig harmlos zu machen. Bei den meisten Techniken auf dieser Seite <!--
bleiben Dinge wie nicht geschlossene Kommentare ( ) und spitze Klammern, die nicht Teil von tags ( blah <<<><blah
) sind, intakt. Die HTMLParser-Version kann sogar vollständige Tags hinterlassen, wenn sie sich in einem nicht geschlossenen Kommentar befinden.
Was ist, wenn Ihre Vorlage ist {{ firstname }} {{ lastname }}
? firstname = '<a'
und lastname = 'href="http://evil.com/">'
wird von jedem Tag-Stripper auf dieser Seite (außer @Medeiros!) durchgelassen, da es sich nicht um vollständige Tags handelt. Das Entfernen normaler HTML-Tags reicht nicht aus.
Django's strip_tags
, eine verbesserte (siehe nächste Überschrift) Version der Top-Antwort auf diese Frage, gibt die folgende Warnung:
Es wird absolut KEINE Garantie dafür gegeben, dass die resultierende Zeichenfolge HTML-sicher ist. Markieren Sie das Ergebnis eines strip_tags
Anrufs also NIEMALS als sicher , ohne ihn zuerst zu umgehen, z. B. mit escape()
.
Folgen Sie ihrem Rat!
Um Tags mit HTMLParser zu entfernen, müssen Sie es mehrmals ausführen.
Es ist einfach, die beste Antwort auf diese Frage zu umgehen.
Schauen Sie sich diese Zeichenfolge an ( Quelle und Diskussion ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
Wenn HTMLParser es zum ersten Mal sieht, kann es nicht erkennen, dass <img...>
es sich um ein Tag handelt. Es sieht kaputt aus, sodass HTMLParser es nicht loswird. Es nimmt nur das heraus <!-- comments -->
und lässt dich mit
<img src=x onerror=alert(1);//>
Dieses Problem wurde dem Django-Projekt im März 2014 mitgeteilt. Ihr altes Problem entsprach im strip_tags
Wesentlichen der Top-Antwort auf diese Frage. Ihre neue Version führt es im Grunde genommen in einer Schleife aus, bis das erneute Ausführen die Zeichenfolge nicht ändert:
# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.
def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags
break
value = new_value
return value
Natürlich ist nichts davon ein Problem, wenn Sie immer dem Ergebnis von entkommen strip_tags()
.
Update 19. März 2015 : In den Django-Versionen vor 1.4.20, 1.6.11, 1.7.7 und 1.8c1 ist ein Fehler aufgetreten. Diese Versionen könnten in der Funktion strip_tags () eine Endlosschleife eingeben. Die feste Version ist oben wiedergegeben. Weitere Details hier .
Gute Dinge zum Kopieren oder Verwenden
Mein Beispielcode verarbeitet keine HTML-Entitäten - die Paketversionen Django und MarkupSafe tun dies.
Mein Beispielcode stammt aus der hervorragenden MarkupSafe- Bibliothek zur Verhinderung von Cross-Site-Scripting. Es ist bequem und schnell (mit C-Beschleunigungen auf die native Python-Version). Es ist in der Google App Engine enthalten und wird von Jinja2 (2.7 und höher) , Mako, Pylons und anderen verwendet. Es funktioniert problemlos mit Django-Vorlagen aus Django 1.7.
Djangos strip_tags und andere HTML-Dienstprogramme aus einer neueren Version sind gut, aber ich finde sie weniger praktisch als MarkupSafe. Sie sind ziemlich eigenständig. Sie können aus dieser Datei kopieren, was Sie benötigen .
Wenn Sie fast alle Tags entfernen müssen, ist die Bleach- Bibliothek gut. Sie können Regeln wie "Meine Benutzer können Dinge kursiv schreiben, aber sie können keine Iframes erstellen" erzwingen lassen.
Verstehen Sie die Eigenschaften Ihres Tag Strippers! Führen Sie Fuzz-Tests durch! Hier ist der Code, mit dem ich nach dieser Antwort gesucht habe.
verlegener Hinweis - Bei der Frage selbst geht es um das Drucken auf der Konsole. Dies ist jedoch das beste Google-Ergebnis für "Python-Strip-HTML von Zeichenfolge". Aus diesem Grund bezieht sich diese Antwort zu 99% auf das Web.
&
. B. ). Sie können entweder 1) sie zusammen mit den Tags entfernen (oft unerwünscht und unnötig, da sie einfachem Text entsprechen), 2) sie unverändert lassen (eine geeignete Lösung, wenn der gestrippte Text direkt in einen HTML-Kontext zurückkehrt) oder 3) ) dekodieren Sie sie in einfachen Text (wenn der gestrippte Text in eine Datenbank oder einen anderen Nicht-HTML-Kontext verschoben wird oder wenn Ihr Webframework automatisch HTML-Escapezeichen für Sie ausführt).