短縮版!
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)
正規表現のソース:MarkupSafe。これらのバージョンはHTMLエンティティも処理しますが、この簡単なバージョンは処理しません。
タグを削除してそのままにできないのはなぜですか?
人を浮かば<i>italicizing</i>せずに、人を物事から遠ざけることは、1つのことiです。しかし、任意の入力を取り、それを完全に無害にすることは別の方法です。このページのほとんどのテクニックでは、閉じられていないコメント(<!--)やタグの一部ではない山括弧(blah <<<><blah)などをそのまま残します。HTMLParserバージョンでは、タグが閉じられていないコメント内にある場合でも、完全なタグを残すことができます。
あなたのテンプレートがどうなったら{{ firstname }} {{ lastname }}? firstname = '<a'またlastname = 'href="http://evil.com/">'、このページのすべてのタグストリッパー(@Medeiros!を除く)によって許可されます。これらはそれ自体では完全なタグではないためです。通常のHTMLタグを取り除くだけでは不十分です。
Django strip_tagsは、この質問に対するトップアンサーの改良(次の見出しを参照)バージョンであり、次の警告を出します。
結果の文字列がHTMLセーフであるという保証は一切ありません。したがってstrip_tags、たとえばを使用して、最初にエスケープせずに呼び出しの結果を安全とマークしないでくださいescape()。
彼らのアドバイスに従ってください!
HTMLParserでタグを取り除くには、タグを複数回実行する必要があります。
この質問に対するトップ回答を簡単に回避することは簡単です。
この文字列を見てください(ソースとディスカッション):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
HTMLParserがそれを初めて見たとき、それが<img...>タグであることを認識できません。壊れているように見えるので、HTMLParserはそれを取り除きません。それだけ<!-- comments -->で、あなたを残して
<img src=x onerror=alert(1);//>
この問題は、2014年3月にDjangoプロジェクトに公開されました。彼らの古い問題はstrip_tags、この質問のトップアンサーと基本的に同じでした。 彼らの新しいバージョンは基本的にループで実行され、再度実行しても文字列は変更されません。
# _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
もちろん、の結果を常にエスケープする場合、これは問題になりませんstrip_tags()。
2015年3月19日更新:1.4.20、1.6.11、1.7.7、および1.8c1より前のDjangoバージョンにはバグがありました。これらのバージョンは、strip_tags()関数で無限ループに入る可能性があります。修正バージョンは上記で再現されています。 詳細はこちら。
コピーまたは使用する良いもの
私のサンプルコードはHTMLエンティティを処理しません-DjangoとMarkupSafeのパッケージバージョンは処理します。
私のサンプルコードは、クロスサイトスクリプティング防止のための優れたMarkupSafeライブラリから抜粋したものです。便利で高速です(CはネイティブのPythonバージョンに高速化されています)。Google App Engineに含まれており、Jinja2(2.7以降)で使用されています、Mako、Pylonsています。Django 1.7のDjangoテンプレートで簡単に動作します。
Djangoのstrip_tagsやその他の最新バージョンのhtmlユーティリティは優れていますが、MarkupSafeほど便利ではありません。それらはかなり自己完結型であり、必要なものをこのファイルからコピーできます。
ほとんどすべてのタグを取り除く必要がある場合は、Bleachライブラリが最適です。「ユーザーはイタリックにすることはできますが、iframeを作成することはできません」などのルールを適用することができます。
タグストリッパーの特性を理解しましょう!ファズテストを実行してください! これが、この回答の調査に使用したコードです。
sheepish note-質問自体はコンソールへの印刷に関するものですが、これは「文字列からのpythonストリップHTML」のGoogleの上位の結果です。そのため、この答えはWebに関する99%です。
&です。1)タグと一緒に削除する(多くの場合望ましくない、プレーンテキストと同等であるため不要)、2)変更せずに残す(ストリップされたテキストがHTMLコンテキストに戻る場合の適切な解決策)、または3 )それらをプレーンテキストにデコードします(除去されたテキストがデータベースまたは他の非HTMLコンテキストに送られる場合、またはWebフレームワークが自動的にテキストのHTMLエスケープを実行する場合)。