cgi.escape dường như là một lựa chọn có thể. Nó có hoạt động tốt không? Có một cái gì đó được coi là tốt hơn?
cgi.escape dường như là một lựa chọn có thể. Nó có hoạt động tốt không? Có một cái gì đó được coi là tốt hơn?
Câu trả lời:
cgi.escape
Ổn. Nó trốn thoát:
<
đến <
>
đến >
&
đến &
Thế là đủ cho tất cả HTML.
EDIT: Nếu bạn có ký tự không phải mã ascii, bạn cũng muốn thoát, để đưa vào một tài liệu được mã hóa khác sử dụng mã hóa khác, như Craig nói, chỉ cần sử dụng:
data.encode('ascii', 'xmlcharrefreplace')
Đừng quên để decode data
để unicode
đầu tiên, sử dụng bất cứ mã hóa nó đã được mã hóa.
Tuy nhiên theo kinh nghiệm của tôi, loại mã hóa là vô dụng nếu bạn chỉ làm việc với unicode
tất cả thời gian từ đầu. Chỉ cần mã hóa ở cuối mã hóa được chỉ định trong tiêu đề tài liệu ( utf-8
để tương thích tối đa).
Thí dụ:
>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'<a>bá</a>
Cũng đáng lưu ý (cảm ơn Greg) là quote
tham số thêm cgi.escape
mất. Với nó được đặt thành True
, cgi.escape
cũng thoát khỏi ký tự trích dẫn kép ( "
) để bạn có thể sử dụng giá trị kết quả trong thuộc tính XML / HTML.
EDIT: Lưu ý rằng cgi.escape đã không được dùng trong Python 3.2 html.escape
, điều này cũng tương tự ngoại trừ quote
mặc định là True.
cgi.escape
chức năng, liệu có đủ để bảo vệ chống lại tất cả các attacs XSS (đã biết) không?
cgi.escape(yourunicodeobj).encode('ascii', 'xmlcharrefreplace') == '{{Measures 12 Ω"H x 17 5/8"W x 8 7/8"D. Imported.}}'
- như bạn có thể thấy, biểu thức trả về ascii bytestring, với tất cả các ký tự unicode không mã hóa được mã hóa bằng bảng tham chiếu ký tự xml.
Trong Python 3.2, một html
mô-đun mới đã được giới thiệu, được sử dụng để thoát các ký tự dành riêng khỏi đánh dấu HTML.
Nó có một chức năng 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()
không có dấu ngoặc kép, theo mặc định (ngược lại, cgi.quote()
không - và chỉ thoát dấu ngoặc kép, nếu được nói như vậy). Vì vậy, tôi phải đặt một cách rõ ràng một tham số tùy chọn để đưa một cái gì đó vào một thuộc tính html.escape()
, nghĩa là làm cho nó không an toàn cho các thuộc tính:t = '" onclick="alert()'; t = html.escape(t, quote=False); s = f'<a href="about.html" class="{t}">foo</a>'
escape()
là không đủ để làm cho các thuộc tính an toàn. Nói cách khác, điều này không an toàn:<a href=" {{ html.escape(untrusted_text) }} ">
href
là đặt Chính sách bảo mật nội dung không tuân theo nó.
html.escape
không thoát dấu ngoặc đơn và dấu ngoặc kép.
Nếu bạn muốn thoát HTML trong một URL:
Đây có lẽ KHÔNG phải là điều OP muốn (câu hỏi không chỉ rõ trong bối cảnh thoát được sử dụng trong bối cảnh nào), nhưng urllib của thư viện riêng của Python có một phương pháp để thoát các thực thể HTML cần được đưa vào URL một cách an toàn.
Sau đây là một ví dụ:
#!/usr/bin/python
from urllib import quote
x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'
Ngoài ra còn có gói markupsafe tuyệt vời .
>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'<script>alert(document.cookie);</script>')
Các markupsafe
gói phần mềm được thiết kế tốt, và có lẽ là hầu hết các linh hoạt và Pythonic cách để đi về thoát, IMHO, bởi vì:
Markup
) là một lớp có nguồn gốc từ unicode (nghĩa làisinstance(escape('str'), unicode) == True
__html__
tính) và quá tải mẫu ( __html_format__
).cgi.escape
nên thoát HTML theo nghĩa hạn chế thoát các thẻ HTML và các thực thể ký tự.
Nhưng bạn cũng có thể phải xem xét các vấn đề mã hóa: nếu HTML bạn muốn trích dẫn có các ký tự không phải ASCII trong một mã hóa cụ thể, thì bạn cũng phải quan tâm rằng bạn thể hiện những điều đó một cách hợp lý khi trích dẫn. Có lẽ bạn có thể chuyển đổi chúng thành các thực thể. Mặt khác, bạn nên đảm bảo rằng các bản dịch mã hóa chính xác được thực hiện giữa HTML "nguồn" và trang được nhúng vào, để tránh làm hỏng các ký tự không phải ASCII.
Không có thư viện, python thuần, thoát văn bản thành văn bản html một cách an toàn:
text.replace('&', '&').replace('>', '>').replace('<', '<'
).encode('ascii', 'xmlcharrefreplace')
<
sẽ được thoát đến&lt;
cgi.escape
đa thế hệPhiên bản này được cải thiện cgi.escape
. Nó cũng bảo tồn khoảng trắng và dòng mới. Trả về một unicode
chuỗi.
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"'
Không phải là cách dễ nhất, nhưng vẫn đơn giản. Sự khác biệt chính từ mô-đun cgi.escape - nó vẫn sẽ hoạt động bình thường nếu bạn đã có &
trong văn bản của mình. Như bạn thấy từ các bình luận cho nó:
phiên bản 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
phiên bản regex
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)
Đối với mã kế thừa trong Python 2.7, có thể thực hiện thông qua BeautifulSoup4 :
>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&d'