cgi.escape здається одним із можливих варіантів. Це добре працює? Чи є щось, що вважається кращим?
cgi.escape здається одним із можливих варіантів. Це добре працює? Чи є щось, що вважається кращим?
Відповіді:
cgi.escape
добре. Це втече:
<
до <
>
до >
&
до &
Цього достатньо для всього HTML.
EDIT: Якщо у вас є символи, що не мають права 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.
EDIT: Зауважте, що 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, з усіма символами unicode 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-адресі:
Це, мабуть, НЕ, чого хотіла ОП (питання не чітко вказує, в якому контексті передбачається використовувати епізод), але у власній URL-адресі бібліотеки Python є метод уникнути 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
) - клас, похідний від unicode (тобто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'