cgi.escape scheint eine mögliche Wahl zu sein. Funktioniert es gut Gibt es etwas, das als besser angesehen wird?
cgi.escape scheint eine mögliche Wahl zu sein. Funktioniert es gut Gibt es etwas, das als besser angesehen wird?
Antworten:
cgi.escape
ist gut. Es entkommt:
<
zu <
>
zu >
&
zu &
Das reicht für alles HTML.
BEARBEITEN: Wenn Sie Nicht-ASCII-Zeichen haben, möchten Sie auch entkommen, um sie in ein anderes codiertes Dokument aufzunehmen, das eine andere Codierung verwendet, wie Craig sagt. Verwenden Sie einfach:
data.encode('ascii', 'xmlcharrefreplace')
Vergessen Sie nicht , zu dekodieren , data
um unicode
erste, mit was auch immer dafür kodierenden codiert wurde.
Nach meiner Erfahrung ist diese Art der Codierung jedoch nutzlos, wenn Sie unicode
von Anfang an immer mit ihnen arbeiten. Codieren Sie einfach am Ende mit der im Dokumentkopf angegebenen Codierung ( utf-8
für maximale Kompatibilität).
Beispiel:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Bemerkenswert (danke Greg) ist auch der zusätzliche quote
Parameter cgi.escape
. Wenn es auf gesetzt ist, True
wird cgi.escape
auch chars ( "
) in doppelten Anführungszeichen maskiert, sodass Sie den resultierenden Wert in einem XML / HTML-Attribut verwenden können.
BEARBEITEN: Beachten Sie, dass cgi.escape in Python 3.2 zugunsten von veraltet ist html.escape
, was dasselbe tut, außer dass quote
standardmäßig True verwendet wird.
cgi.escape
Funktion ausführe , reicht dies aus, um mich vor allen (bekannten) XSS-Attacs zu schützen?
cgi.escape(yourunicodeobj).encode('ascii', 'xmlcharrefreplace') == '{{Measures 12 Ω"H x 17 5/8"W x 8 7/8"D. Imported.}}'
- Wie Sie sehen können, gibt der Ausdruck ASCII-Bytestring zurück, wobei alle Nicht-ASCII-Unicode-Zeichen mithilfe der XML-Zeichenreferenztabelle codiert werden.
In Python 3.2 wurde ein neues html
Modul eingeführt, mit dem reservierte Zeichen aus dem HTML-Markup entfernt werden.
Es hat eine Funktion escape()
:
>>> import html
>>> html.escape('x > 2 && x < 7 single quote: \' double quote: "')
'x > 2 && x < 7 single quote: ' double quote: "'
quote=True
?
html.escape()
Anführungszeichen standardmäßig nicht verwendet werden (im Gegensatz dazu cgi.quote()
nicht - und nur doppelte Anführungszeichen, wenn dies mitgeteilt wird). Daher muss ich explizit einen optionalen Parameter festlegen, um etwas in ein Attribut html.escape()
t = '" onclick="alert()'; t = html.escape(t, quote=False); s = f'<a href="about.html" class="{t}">foo</a>'
escape()
es nicht ausreicht, um Attribute sicher zu machen. Mit anderen Worten, dies ist nicht sicher:<a href=" {{ html.escape(untrusted_text) }} ">
href
ist das Festlegen einer Inhaltssicherheitsrichtlinie, die dies nicht zulässt.
html.escape
einfache Anführungszeichen und doppelte Anführungszeichen entgehen.
Wenn Sie HTML in einer URL maskieren möchten:
Dies ist wahrscheinlich NICHT das, was das OP wollte (die Frage gibt nicht eindeutig an, in welchem Kontext das Escapezeichen verwendet werden soll), aber Pythons native Bibliothek urllib verfügt über eine Methode, um HTML-Entitäten zu maskieren, die sicher in eine URL aufgenommen werden müssen.
Das Folgende ist ein Beispiel:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
Es gibt auch das ausgezeichnete markupsafe Paket .
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
Das markupsafe
Paket ist ausgereift und wahrscheinlich der vielseitigste und pythonischste Weg, um zu entkommen, IMHO, weil:
Markup
) ist eine von Unicode abgeleitete Klasse (dhisinstance(escape('str'), unicode) == True
__html__
Eigenschaft) und Vorlagenüberladungen ( __html_format__
).cgi.escape
sollte gut sein, um HTML im begrenzten Sinne der HTML-Tags und Zeichenentitäten zu entkommen.
Möglicherweise müssen Sie jedoch auch Codierungsprobleme berücksichtigen: Wenn der HTML-Code, den Sie zitieren möchten, Nicht-ASCII-Zeichen in einer bestimmten Codierung enthält, müssen Sie auch darauf achten, dass Sie diese beim Zitieren sinnvoll darstellen. Vielleicht könnten Sie sie in Entitäten konvertieren. Andernfalls sollten Sie sicherstellen, dass die korrekten Codierungsübersetzungen zwischen dem HTML-Quellcode und der eingebetteten Seite durchgeführt werden, um eine Beschädigung der Nicht-ASCII-Zeichen zu vermeiden.
Keine Bibliotheken, reines Python, entkommen sicher Text in HTML-Text:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
<
wird entkommen&lt;
cgi.escape
verlängertDiese Version verbessert sich cgi.escape
. Außerdem bleiben Leerzeichen und Zeilenumbrüche erhalten. Gibt eine unicode
Zeichenfolge zurück.
def escape_html(text):
"""escape strings for display in HTML"""
return cgi.escape(text, quote=True).\
replace(u'\n', u'<br />').\
replace(u'\t', u' ').\
replace(u' ', u' ')
>>> escape_html('<foo>\nfoo\t"bar"')
u'<foo><br />foo "bar"'
Nicht der einfachste Weg, aber dennoch unkompliziert. Der Hauptunterschied zum cgi.escape- Modul - es funktioniert immer noch einwandfrei, wenn Sie es bereits &
in Ihrem Text haben. Wie Sie aus den Kommentaren sehen:
cgi.escape Version
def escape(s, quote=None):
'''Replace special characters "&", "<" and ">" to HTML-safe sequences.
If the optional flag quote is true, the quotation mark character (")
is also translated.'''
s = s.replace("&", "&") # Must be done first!
s = s.replace("<", "<")
s = s.replace(">", ">")
if quote:
s = s.replace('"', """)
return s
Regex-Version
QUOTE_PATTERN = r"""([&<>"'])(?!(amp|lt|gt|quot|#39);)"""
def escape(word):
"""
Replaces special characters <>&"' to HTML-safe sequences.
With attention to already escaped characters.
"""
replace_with = {
'<': '>',
'>': '<',
'&': '&',
'"': '"', # should be escaped in attributes
"'": ''' # should be escaped in attributes
}
quote_pattern = re.compile(QUOTE_PATTERN)
return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], word)
Für Legacy-Code in Python 2.7 ist dies über BeautifulSoup4 möglich :
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'