Cgi.escape кажется одним из возможных вариантов. Это хорошо работает? Есть ли что-то, что считается лучше?
Cgi.escape кажется одним из возможных вариантов. Это хорошо работает? Есть ли что-то, что считается лучше?
Ответы:
cgi.escape
Это хорошо. Это ускользает от:
<
в <
>
в >
&
в &
Этого достаточно для всего HTML.
РЕДАКТИРОВАТЬ: Если у вас есть не ascii символы, которые вы также хотите экранировать, для включения в другой кодированный документ, который использует другую кодировку, как говорит Крейг , просто используйте:
data.encode('ascii', 'xmlcharrefreplace')
Не забудьте декодирование data
к unicode
первому, используя любой кодирующим он был закодирован.
Однако, по моему опыту, такая кодировка бесполезна, если вы просто unicode
все время работаете с самого начала. Просто закодируйте в конце кодировку, указанную в заголовке документа ( utf-8
для максимальной совместимости).
Пример:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Также стоит отметить (спасибо Грег) дополнительный quote
параметр cgi.escape
принимает. С ней установлена True
, cgi.escape
также экранирует двойные кавычки символов ( "
) , так что вы можете использовать полученное значение в атрибуте XML / HTML.
РЕДАКТИРОВАТЬ: Обратите внимание, что cgi.escape устарела в Python 3.2 в пользу html.escape
, который делает то же самое, за исключением того, что по quote
умолчанию True.
cgi.escape
функцию, достаточно ли защиты от всех (известных) атак XSS?
cgi.escape(yourunicodeobj).encode('ascii', 'xmlcharrefreplace') == '{{Measures 12 Ω"H x 17 5/8"W x 8 7/8"D. Imported.}}'
- как вы можете видеть, выражение возвращает ascii bytestring со всеми не-ascii символами Unicode, закодированными с использованием справочной таблицы символов xml.
В Python 3.2 html
был представлен новый модуль, который используется для экранирования зарезервированных символов из разметки HTML.
Имеет одну функцию 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()
по умолчанию экранирует кавычки (в отличие от cgi.quote()
этого - не экранирует двойные кавычки, если так сказано). Таким образом, я должен явно установить необязательный параметр, чтобы внедрить что-либо в атрибут html.escape()
, то есть сделать его небезопасным для атрибутов:t = '" onclick="alert()'; t = html.escape(t, quote=False); s = f'<a href="about.html" class="{t}">foo</a>'
escape()
что недостаточно, чтобы сделать атрибуты безопасными. Другими словами, это небезопасно:<a href=" {{ html.escape(untrusted_text) }} ">
href
- установить Политику безопасности контента, которая запрещает ее.
html.escape
что экранирует одинарные и двойные кавычки.
Если вы хотите экранировать HTML в URL:
Вероятно, это НЕ то, что хотел ОП (вопрос не ясно указывает, в каком контексте предполагается использовать экранирование), но в родной библиотеке Python urllib есть метод для экранирования сущностей HTML, которые необходимо безопасно включать в URL.
Ниже приведен пример:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
Существует также превосходный пакет markupsafe .
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
markupsafe
Пакет хорошо разработан, и , вероятно , самый универсальный и Pythonic путь о побеге, ИМХО, потому что:
Markup
) - это класс, полученный из юникода (т.е.isinstance(escape('str'), unicode) == True
__html__
свойством) и перегрузки шаблона ( __html_format__
).cgi.escape
должно быть хорошо избегать HTML в ограниченном смысле, избегая тегов HTML и символьных сущностей.
Но вам, возможно, придется учитывать и проблемы с кодировкой: если HTML-код, который вы хотите процитировать, содержит символы, не входящие в ASCII, в определенной кодировке, вам также следует позаботиться о том, чтобы вы представляли их разумно при цитировании. Возможно, вы могли бы преобразовать их в сущности. В противном случае вы должны убедиться, что между исходным HTML и страницей, в которую он встроен, сделаны правильные переводы кодировки, чтобы не повредить не-ASCII-символы.
Нет библиотек, чистый Python, безопасно экранирует текст в HTML-текст:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
<
будет спасен&lt;
cgi.escape
расширенныйЭта версия улучшается cgi.escape
. Это также сохраняет пробелы и переводы строки. Возвращает unicode
строку.
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"'
Не самый простой способ, но все же простой. Основное отличие от модуля cgi.escape - он все равно будет работать правильно, если у вас уже есть &
текст. Как видно из комментариев к нему:
версия cgi.escape
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
версия регулярного выражения
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)
Для устаревшего кода в Python 2.7, можете сделать это через BeautifulSoup4 :
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'