Phiên bản ngắn!
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)
Nguồn Regex: MarkupSafe . Phiên bản của họ cũng xử lý các thực thể HTML, trong khi phiên bản nhanh này thì không.
Tại sao tôi không thể tách các thẻ và để lại nó?
Đó là một điều để giữ mọi người khỏi <i>italicizing</i>
mọi thứ, mà không để lại i
nổi xung quanh. Nhưng đó là một cách khác để có đầu vào tùy ý và làm cho nó hoàn toàn vô hại. Hầu hết các kỹ thuật trên trang này sẽ để lại những thứ như bình luận không được tiết lộ ( <!--
) và dấu ngoặc nhọn không blah <<<><blah
còn nguyên vẹn của thẻ ( ). Phiên bản HTMLParser thậm chí có thể để lại các thẻ hoàn chỉnh, nếu chúng nằm trong một nhận xét không được tiết lộ.
Nếu mẫu của bạn là {{ firstname }} {{ lastname }}
gì? firstname = '<a'
và lastname = 'href="http://evil.com/">'
sẽ được thông qua bởi mọi trình gỡ thẻ trên trang này (ngoại trừ @Medeiros!), vì chúng không tự hoàn thành các thẻ. Tước các thẻ HTML bình thường là không đủ.
Django strip_tags
, một phiên bản cải tiến (xem tiêu đề tiếp theo) của câu trả lời hàng đầu cho câu hỏi này, đưa ra cảnh báo sau:
Tuyệt đối KHÔNG đảm bảo được cung cấp về chuỗi kết quả là HTML an toàn. Vì vậy, KHÔNG BAO GIỜ đánh dấu an toàn kết quả của một strip_tags
cuộc gọi mà không thoát khỏi cuộc gọi trước, ví dụ như với escape()
.
Làm theo lời khuyên của họ!
Để loại bỏ các thẻ bằng HTMLParser, bạn phải chạy nó nhiều lần.
Thật dễ dàng để vượt qua câu trả lời hàng đầu cho câu hỏi này.
Nhìn vào chuỗi này ( nguồn và thảo luận ):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
Lần đầu tiên HTMLParser nhìn thấy nó, nó không thể nói rằng đó <img...>
là một thẻ. Nó trông có vẻ bị hỏng, vì vậy HTMLParser không thoát khỏi nó. Nó chỉ lấy ra <!-- comments -->
, để lại cho bạn
<img src=x onerror=alert(1);//>
Vấn đề này đã được tiết lộ cho dự án Django vào tháng 3 năm 2014. Câu hỏi cũ của họ strip_tags
về cơ bản giống như câu trả lời hàng đầu cho câu hỏi này. Phiên bản mới của họ về cơ bản chạy nó trong một vòng lặp cho đến khi chạy lại nó không thay đổi chuỗi:
# _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
Tất nhiên, không có gì trong số này là vấn đề nếu bạn luôn thoát khỏi kết quả strip_tags()
.
Cập nhật ngày 19 tháng 3 năm 2015 : Có lỗi trong các phiên bản Django trước 1.4.20, 1.6.11, 1.7.7 và 1.8c1. Các phiên bản này có thể nhập một vòng lặp vô hạn trong hàm dải_t_t (). Phiên bản cố định được sao chép ở trên. Thêm chi tiết tại đây .
Những điều tốt để sao chép hoặc sử dụng
Mã ví dụ của tôi không xử lý các thực thể HTML - phiên bản đóng gói Django và MarkupSafe.
Mã ví dụ của tôi được lấy từ thư viện MarkupSafe tuyệt vời để ngăn chặn kịch bản chéo trang. Thật tiện lợi và nhanh chóng (với việc tăng tốc độ C lên phiên bản Python gốc). Nó được bao gồm trong Google App Engine và được sử dụng bởi Jinja2 (2.7 trở lên) , Mako, Pylons, v.v. Nó hoạt động dễ dàng với các mẫu Django từ Django 1.7.
Strip_tags của Django và các tiện ích html khác từ phiên bản gần đây là tốt, nhưng tôi thấy chúng không tiện lợi hơn MarkupSafe. Chúng khá khép kín, bạn có thể sao chép những gì bạn cần từ tệp này .
Nếu bạn cần loại bỏ gần như tất cả các thẻ, thư viện Bleach là tốt. Bạn có thể yêu cầu nó thực thi các quy tắc như "người dùng của tôi có thể in nghiêng mọi thứ, nhưng họ không thể tạo ra iframe."
Hiểu các thuộc tính của vũ nữ thoát y thẻ của bạn! Chạy thử nghiệm fuzz trên đó! Đây là mã tôi đã sử dụng để thực hiện nghiên cứu cho câu trả lời này.
lưu ý ngớ ngẩn - Bản thân câu hỏi là về việc in lên bàn điều khiển, nhưng đây là kết quả hàng đầu của Google cho "chuỗi python html từ chuỗi", vì vậy đó là lý do tại sao câu trả lời này là 99% về web.
&
). Bạn có thể 1) xóa chúng cùng với các thẻ (thường không mong muốn và không cần thiết vì chúng tương đương với văn bản thuần túy), 2) không thay đổi chúng (một giải pháp phù hợp nếu văn bản bị tước sẽ quay lại ngữ cảnh HTML) hoặc 3 ) giải mã chúng thành văn bản thuần túy (nếu văn bản bị tước đi vào cơ sở dữ liệu hoặc một số bối cảnh không phải HTML khác hoặc nếu khung web của bạn tự động thực hiện thoát văn bản HTML cho bạn).