XSSFilter.py
from bs4 import BeautifulSoup
class XSSFilter(object):
__instance = None
def __init__(self):
# XSS白名单
self.valid_tags = {
"font": ['color', 'size', 'face', 'style'],
'b': [],
'div': [],
"span": [],
"table": [
'border', 'cellspacing', 'cellpadding'
],
'th': [
'colspan', 'rowspan'
],
'td': [
'colspan', 'rowspan'
],
"a": ['href', 'target', 'name'],
"img": ['src', 'alt', 'title'],
'p': [
'align'
],
"pre": ['class'],
"hr": ['class'],
'strong': []
}
def __new__(cls, *args, **kwargs):
"""
单例模式
:param cls:
:param args:
:param kwargs:
:return:
"""
if not cls.__instance:
obj = object.__new__(cls, *args, **kwargs)
cls.__instance = obj
return cls.__instance
def process(self, content):
soup = BeautifulSoup(content, 'html.parser')
# 遍历所有HTML标签
for tag in soup.find_all(recursive=True):
# 判断标签名是否在白名单中
if tag.name not in self.valid_tags:
tag.hidden = True
if tag.name not in ['html', 'body']:
tag.hidden = True
tag.clear()
continue
# 当前标签的所有属性白名单
attr_rules = self.valid_tags[tag.name]
keys = list(tag.attrs.keys())
for key in keys:
if key not in attr_rules:
del tag[key]
return soup.decode()
if __name__ == '__main__':
html = """<p class="title">
<b>The Dormouse's story</b>
</p>
<p class="story">
<div name='root'>
Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister c1" style='color:red;background-color:green;' id="link1"><!-- Elsie --></a>
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tilffffffffffffflie</a>;
and they lived at the bottom of a well.
<script>alert(123)</script>
</div>
</p>
<p class="story">...</p>"""
obj = XSSFilter()
v = obj.process(html)
print(v)
应用:
@check_login
def add_article(request):
if request.method == 'GET':
form = ArticleForm(request=request)
return render(request, 'backend_add_article.html', {'form': form})
elif request.method == 'POST':
form = ArticleForm(request=request, data=request.POST)
if form.is_valid():
with transaction.atomic(): # from django.db import transaction
...
content = form.cleaned_data.pop('content')
content = XSSFilter().process(content)
models.ArticleDetail.objects.create(content=content, article=obj)
...
return redirect('/backend/article-0-0.html')
else:
return render(request, 'backend_add_article.html', {'form': form})
else:
return redirect('/')
@check_login
def update_article(request):
...
elif request.method == 'POST':
form = ArticleForm(request=request, data=request.POST)
if form.is_valid():
obj = models.Article.objects.filter(nid=nid, blog_id=blog_id).first()
if not obj:
return render(request, 'backend_no_article.html')
with transaction.atomic():
content = form.cleaned_data.pop('content')
content = XSSFilter().process(content)
tags = form.cleaned_data.pop('tags')
models.Article.objects.filter(nid=obj.nid).update(**form.cleaned_data)
models.ArticleDetail.objects.filter(article=obj).update(content=content)
models.Article2Tag.objects.filter(article=obj).delete()
tag_list = []
for tag_id in tags:
tag_id = int(tag_id)
tag_list.append(models.Article2Tag(article_id=obj.nid, tag_id=tag_id))
models.Article2Tag.objects.bulk_create(tag_list)
return redirect('/backend/article-0-0.html')
else:
return render(request, 'backend_edit_article.html', {'form': form, 'nid': nid})
标签:XSS,obj,form,三十二,request,content,tag,article
From: https://www.cnblogs.com/zhlforhe/p/18014238