标签:link int mic 迭代 作用 设计 height ict 就是
用python做web开发时,必须要考虑到防止用户的XSS注入。当然我们可以自己写白名单,然后通过BeatifulSoup等处理html的库来进行标签和属性的过滤。Bleach是一个实现上述功能的python库,官网是这样描述的:
Bleach is a allowed-list-based HTML sanitizing library that escapes or strips markup and attributes.
Bleach can also linkify text safely, applying filters that Django’s
urlize
filter cannot, and optionally settingrel
attributes, even on links already in the text.Bleach is intended for sanitizing text from untrusted sources. If you find yourself jumping through hoops to allow your site administrators to do lots of things, you’re probably outside the use cases. Either trust those users, or don’t.
Because it relies on html5lib, Bleach is as good as modern browsers at dealing with weird, quirky HTML fragments. And any of Bleach’s methods will fix unbalanced or mis-nested tags.
拙劣地翻译一下:
bleach是一个基于白名单、通过转义或去除标签和属性的方式,来对HTML文本净化的python库。
除此之外,bleach还能安全地链接文本,它所提供的过滤器,可以过滤掉django的
urlize过滤器所不能过滤的内容,并且可以随意的设置rel属性,即使是已经存在于文本中的链接。
bleach 设计的目的在于对不可信来源数据的净化。如果你发现自己总是依赖你的网站管理员做很多事情,那你可能不适合使用它的场景里。要么相信要用户,要么就不去相信。
由于bleach依赖html5lib,因此它在现代浏览器上处理一些奇怪的HTML标签依然好用。它的任何方法都能帮助修复错乱的或嵌套的标签。
知道bleach的作用后,现在来安装它。Bleach在PyPI上可用,因此可用通过pip或easy_install来安装:
$ pip install bleach
$ easy_install bleach
>>> import bleach >>> bleach.clean(‘an <script>evil()</script> example‘) u‘an <script>evil()</script> example‘ >>> bleach.linkify(‘an http://example.com url‘) u‘an <a href="http://example.com" rel="nofollow">http://example.com</a> url
这样就能做一些简单的html过滤了。
文本内容过滤:
bleach.clean()
用于对HTML片段进行过滤的方法 需要注意的是,该方法过滤的是片段而非整个HTML文档,当不传任何参数时,它只用来过滤HTML标签,不包括属性、CSS, JSON, xhtml, SVG等其他内容。
因此对一些存在风险的属性的渲染过程中,需要用模板转义一下。 如果你正在清理大量的文本并传递相同的参数值或者你想要更多的可配置性,可以考虑使用bleach.sanitizer.Cleaner 实例。
参数解读:
返回值:
Unicode格式的文本
各参数的简单示例:
# tag参数示例 >>> import bleach >>> bleach.clean( ... u‘<b><i>an example</i></b>‘, ... tags=[‘b‘], ... ) u‘<b><i>an example</i></b>‘ # attributes为list示例 >>> import bleach >>> bleach.clean( ... u‘<p class="foo" style="color: red; font-weight: bold;">blah blah blah</p>‘, ... tags=[‘p‘], ... attributes=[‘style‘], ... styles=[‘color‘], ... ) u‘<p style="color: red;">blah blah blah</p>‘ # attributes为dict示例 >>> import bleach >>> attrs = { ... ‘*‘: [‘class‘], ... ‘a‘: [‘href‘, ‘rel‘], ... ‘img‘: [‘alt‘], ... } >>> bleach.clean( ... u‘<img alt="an example" width=500>‘, ... tags=[‘img‘], ... attributes=attrs ... ) u‘<img alt="an example">‘ # attributes为function示例 >>> import bleach >>> def allow_h(tag, name, value): ... return name[0] == ‘h‘ >>> bleach.clean( ... u‘<a href="http://example.com" title="link">link</a>‘, ... tags=[‘a‘], ... attributes=allow_h, ... ) u‘<a href="http://example.com">link</a>‘ >>> from urlparse import urlparse >>> import bleach >>> def allow_src(tag, name, value): ... if name in (‘alt‘, ‘height‘, ‘width‘): ... return True ... if name == ‘src‘: ... p = urlparse(value) ... return (not p.netloc) or p.netloc == ‘mydomain.com‘ ... return False >>> bleach.clean( ... u‘<img src="http://example.com" alt="an example">‘, ... tags=[‘img‘], ... attributes={ ... ‘img‘: allow_src ... } ... ) u‘<img alt="an example">‘ # style参数示例 >>> import bleach >>> tags = [‘p‘, ‘em‘, ‘strong‘] >>> attrs = { ... ‘*‘: [‘style‘] ... } >>> styles = [‘color‘, ‘font-weight‘] >>> bleach.clean( ... u‘<p style="font-weight: heavy;">my html</p>‘, ... tags=tags, ... attributes=attrs, ... styles=styles ... ) u‘<p style="font-weight: heavy;">my html</p>‘ # protocol参数示例 >>> import bleach >>> bleach.clean( ... ‘<a href="smb://more_text">allowed protocol</a>‘, ... protocols=[‘http‘, ‘https‘, ‘smb‘] ... ) u‘<a href="smb://more_text">allowed protocol</a>‘ >>> import bleach >>> bleach.clean( ... ‘<a href="smb://more_text">allowed protocol</a>‘, ... protocols=bleach.ALLOWED_PROTOCOLS + [‘smb‘] ... ) u‘<a href="smb://more_text">allowed protocol</a>‘ #strip参数示例 >>> import bleach >>> bleach.clean(‘<span>is not allowed</span>‘) u‘<span>is not allowed</span>‘ >>> bleach.clean(‘<b><span>is not allowed</span></b>‘, tags=[‘b‘]) u‘<b><span>is not allowed</span></b>‘ >>> import bleach >>> bleach.clean(‘<span>is not allowed</span>‘, strip=True) u‘is not allowed‘ >>> bleach.clean(‘<b><span>is not allowed</span></b>‘, tags=[‘b‘], strip=True) u‘<b>is not allowed</b>‘ # strip_comments参数示例 >>> import bleach >>> html = ‘my<!-- commented --> html‘ >>> bleach.clean(html) u‘my html‘ >>> bleach.clean(html, strip_comments=False) u‘my<!-- commented --> html‘
bleach.sanitizer.Cleaner
classbleach.sanitizer.
Cleaner
(tags=[u‘a‘, u‘abbr‘, u‘acronym‘, u‘b‘, u‘blockquote‘, u‘code‘, u‘em‘, u‘i‘, u‘li‘, u‘ol‘, u‘strong‘, u‘ul‘], attributes={u‘a‘: [u‘href‘, u‘title‘], u‘acronym‘: [u‘title‘], u‘abbr‘: [u‘title‘]}, styles=[], protocols=[u‘http‘, u‘https‘, u‘mailto‘], strip=False, strip_comments=True, filters=None)
参数基本与clean方法一样,filter参数传入的是一个由html5lib Filter类组成用来传递流内容的列表。
clean方法: 返回值和之前的clean方法一样,但是当传入值不为文本格式时,会引发TypeError异常。
简单示例:
from bleach.sanitizer import Cleaner cleaner = Cleaner() for text in all_the_yucky_things: sanitized = cleaner.clean(text)
关于向filter参数传入html5lib Filter对象,该对象可以自定义过滤操作,可以对传入的文本数据进行增删改,bleach默认操作为删除恶意内容,可以通过该实例在不丢弃内容的前提下,将恶意内容修改为合法内容:
from bleach.sanitizer import Cleaner cleaner = Cleaner() for text in all_the_yucky_things: sanitized = cleaner.clean(text)
bleach.clean()方法实例化了bleach.sanitizer.Cleaner对象,而bleach.sanitizer.Cleaner对象则实例化了bleach.sanitizer.BleachSanitizerFilter对象,而真正实现过滤作用的就是bleach.sanitizer.BleachSanitizerFilter对象。bleach.sanitizer.BleachSanitizerFilter是一个html5lib filter,可以在任何使用html5lib filter的地方使用。
bleach.sanitizer.BleachSanitizerFilter
class bleach.sanitizer.
BleachSanitizerFilter
(source, attributes={u‘a‘: [u‘href‘, u‘title‘], u‘acronym‘: [u‘title‘], u‘abbr‘: [u‘title‘]}, strip_disallowed_elements=False, strip_html_comments=True, **kwargs)
参数与bleach.clean方法一样,strip_disallowed_elements相当于bleach.clean方法的strip参数,strip_html_comments相当于bleach.clean方法的strip_comments参数。
文本内容链接化:
bleach.linkify()
此方法会将html文本中的url形式字符转换为链接。url形式字符包括:url、域名、email等,但在以下情况不会进行转换:
总体来讲,本方法会尽可能多得将文本里的链接形式内容转换为a标签。
bleach.linkifier.Linker 实例
bleach.linkifier.LinkifyFilter,这样可以避免对html文本进行两次解析
bleach.
linkify
(text, callbacks=[<function nofollow>], skip_tags=None, parse_email=False)
参数分析:
bleach.linkifier.DEFAULT_CALLBACKS
其中callbacks参数里的callback函数必须遵循如下格式:
def my_callback(attrs, new=False):
attrs参数和clean方法的参数类似,是由标签和其属性组成键值对的字典。callbacks可以用来为链接化后的标签中加入、删除或修改属性。new参数表明callback执行操作的对象是新的链接化字符(即类url字符,还未转换为链接时),或者是已存在的链接(即已经是链接的字符)。
1.添加属性:
>>> from bleach.linkifier import Linker >>> def set_title(attrs, new=False): ... attrs[(None, u‘title‘)] = u‘link in user text‘ ... return attrs ... >>> linker = Linker(callbacks=[set_title]) >>> linker.linkify(‘abc http://example.com def‘) u‘abc <a href="http://example.com" title="link in user text">http://example.com</a> def‘
将生成的链接设置为内部链接在当前页打开、外部链接在新建页打开的例子:
>>> from urlparse import urlparse >>> from bleach.linkifier import Linker >>> def set_target(attrs, new=False): ... p = urlparse(attrs[(None, u‘href‘)]) ... if p.netloc not in [‘my-domain.com‘, ‘other-domain.com‘]: ... attrs[(None, u‘target‘)] = u‘_blank‘ ... attrs[(None, u‘class‘)] = u‘external‘ ... else: ... attrs.pop((None, u‘target‘), None) ... return attrs ... >>> linker = Linker(callbacks=[set_target]) >>> linker.linkify(‘abc http://example.com def‘) u‘abc <a class="external" href="http://example.com" target="_blank">http://example.com</a> def‘
2.删除属性。通过callback可以进行类似属性白名单过滤操作,删除标签中已有属性,甚至可以删除那些没有经过链接化的文本内容的标签属性,功能与clean方法类似:
>>> from bleach.linkifier import Linker >>> def allowed_attrs(attrs, new=False): ... """Only allow href, target, rel and title.""" ... allowed = [ ... (None, u‘href‘), ... (None, u‘target‘), ... (None, u‘rel‘), ... (None, u‘title‘), ... u‘_text‘, ... ] ... return dict((k, v) for k, v in attrs.items() if k in allowed) ... >>> linker = Linker(callbacks=[allowed_attrs]) >>> linker.linkify(‘<a style="font-weight: super bold;" href="http://example.com">link</a>‘) u‘<a href="http://example.com">link</a>‘
除了删除白名单之外的属性,还可以删除指定属性:
>>> from bleach.linkifier import Linker >>> def remove_title(attrs, new=False): ... attrs.pop((None, u‘title‘), None) ... return attrs ... >>> linker = Linker(callbacks=[remove_title]) >>> linker.linkify(‘<a href="http://example.com">link</a>‘) u‘<a href="http://example.com">link</a>‘ >>> linker.linkify(‘<a title="bad title" href="http://example.com">link</a>‘) u‘<a href="http://example.com">link</a>‘
3.添加属性。可以用来缩短长url在页面上显示的长度:
>>> from bleach.linkifier import Linker >>> def shorten_url(attrs, new=False): ... """Shorten overly-long URLs in the text.""" ... # Only adjust newly-created links ... if not new: ... return attrs ... # _text will be the same as the URL for new links ... text = attrs[u‘_text‘] ... if len(text) > 25: ... attrs[u‘_text‘] = text[0:22] + u‘...‘ ... return attrs ... >>> linker = Linker(callbacks=[shorten_url]) >>> linker.linkify(‘http://example.com/longlonglonglonglongurl‘) u‘<a href="http://example.com/longlonglonglonglongurl">http://example.com/lon...</a>‘
可以让所有链接都通过一个bouncer访问:
>>> from six.moves.urllib.parse import quote, urlparse >>> from bleach.linkifier import Linker >>> def outgoing_bouncer(attrs, new=False): ... """Send outgoing links through a bouncer.""" ... href_key = (None, u‘href‘) ... p = urlparse(attrs.get(href_key, None)) ... if p.netloc not in [‘example.com‘, ‘www.example.com‘, ‘‘]: ... bouncer = ‘http://bn.ce/?destination=%s‘ ... attrs[href_key] = bouncer % quote(attrs[href_key]) ... return attrs ... >>> linker = Linker(callbacks=[outgoing_bouncer]) >>> linker.linkify(‘http://example.com‘) u‘<a href="http://example.com">http://example.com</a>‘ >>> linker.linkify(‘http://foo.com‘) u‘<a href="http://bn.ce/?destination=http%3A//foo.com">http://foo.com</a>‘
防止某些类url格式的字符被转为链接:
>>> from bleach.linkifier import Linker >>> def dont_linkify_python(attrs, new=False): ... # This is an existing link, so leave it be ... if not new: ... return attrs ... # If the TLD is ‘.py‘, make sure it starts with http: or https:. ... # Use _text because that‘s the original text ... link_text = attrs[u‘_text‘] ... if link_text.endswith(‘.py‘) and not link_text.startswith((‘http:‘, ‘https:‘)): ... # This looks like a Python file, not a URL. Don‘t make a link. ... return None ... # Everything checks out, keep going to the next callback. ... return attrs ... >>> linker = Linker(callbacks=[dont_linkify_python]) >>> linker.linkify(‘abc http://example.com def‘) u‘abc <a href="http://example.com">http://example.com</a> def‘ >>> linker.linkify(‘abc models.py def‘) u‘abc models.py def‘
可以进行反链接化操作,即使html文本中已存在的a标签,也可以通过自定制的方式将其逆转为普通字符:
>>> from bleach.linkifier import Linker >>> def remove_mailto(attrs, new=False): ... if attrs[(None, u‘href‘)].startswith(u‘mailto:‘): ... return None ... return attrs ... >>> linker = Linker(callbacks=[remove_mailto]) >>> linker.linkify(‘<a href="mailto:janet@example.com">mail janet!</a>‘) u‘mail janet!‘
bleach.linkifier.Linker实例
当使用一套统一的规则进行文本链接化处理时,推荐使用bleach.linkifier.Linker实例,因为linkify方法的本质就是调用此实例。简单使用:
>>> from bleach.linkifier import Linker >>> linker = Linker(skip_tags=[‘pre‘]) >>> linker.linkify(‘a b c http://example.com d e f‘) u‘a b c <a href="http://example.com" rel="nofollow">http://example.com</a> d e f‘
class
bleach.linkifier.
Linker
(callbacks=[<function nofollow>], skip_tags=None, parse_email=False, url_re=<_sre.SRE_Pattern object at 0x25b8e90>, email_re=<_sre.SRE_Pattern object at 0x258b5f0>)
参数解读:
返回值:链接化的Unicode字符
实例方法:
linkify(text)
参数:text (str) – 需要链接化的html文本
返回值:Unicode文本
异常:当传入值不是文本格式时,引发TypeError异常
bleach.linkifier.LinkifyFilter
bleach.linkify方法就是通过此实例进行链接化的。跟之前讲到过的bleach.linkifier.Cleaner一样,此实例也可以当做html5lib filter实例使用,例如,可以使用此实例,传入到bleach.linkifier.Cleaner中,使得文本过滤和文本链接化同时进行,一步完成。使用默认配置时:
>>> from functools import partial >>> from bleach import Cleaner >>> from bleach.linkifier import LinkifyFilter >>> cleaner = Cleaner(tags=[‘pre‘]) >>> cleaner.clean(‘<pre>http://example.com</pre>‘) u‘<pre>http://example.com</pre>‘ >>> cleaner = Cleaner(tags=[‘pre‘], filters=[LinkifyFilter]) >>> cleaner.clean(‘<pre>http://example.com</pre>‘) u‘<pre><a href="http://example.com">http://example.com</a></pre>‘
传参后对比:
>>> from functools import partial >>> from bleach.sanitizer import Cleaner >>> from bleach.linkifier import LinkifyFilter >>> cleaner = Cleaner( ... tags=[‘pre‘], ... filters=[partial(LinkifyFilter, skip_tags=[‘pre‘])] ... ) ... >>> cleaner.clean(‘<pre>http://example.com</pre>‘) u‘<pre>http://example.com</pre>‘
class
bleach.linkifier.
LinkifyFilter
(source, callbacks=None, skip_tags=None, parse_email=False, url_re=<_sre.SRE_Pattern object at 0x25b8e90>, email_re=<_sre.SRE_Pattern object at 0x258b5f0>)
参数解读:
标签:link int mic 迭代 作用 设计 height ict 就是
原文地址:http://www.cnblogs.com/by3333/p/7737113.html