Django Template - Пометить только определенные HTML-теги как безопасные
У меня есть следующий сценарий использования: пользователь должен иметь возможность вводить HTML ввод и он должен отображаться как таковой. Однако он может содержать только теги <br>, <italic>, <strong>, <ul> or <li>
.
Я знаю о безопасном фильтре, но тогда он будет разрешать каждый HTML-ввод и будет подвержен XSS.
Есть идеи, как я могу решить эту проблему?
Спасибо!
Мы можем сделать валидатор, который разрешает только определенные теги, например, с BeautifulSoup:
from bs4 import BeautifulSoup
from bs4.element import Tag
from django.core.exceptions import ValidationError
from django.utils.deconstruct import deconstructible
@deconstructible
class HtmlValidator:
def __init__(self, tags=()):
self.tags = tags
def validate(self, node):
if isinstance(node, Tag):
if node.name not in self.tags:
raise ValidationError(f'Tag {node.name} is not a valid tag')
for child in node:
self.validate(child)
def __call__(self, value):
soup = BeautifulSoup(value, 'html.parser')
for child in soup:
self.validate(soup)
Тогда мы можем добавить такой валидатор в модель:
class MyModel(models.Model):
content = models.CharField(
max_length=1024,
validators=[HtmlValidator(tags={'br', 'italic', 'strong', 'ul', 'li'})],
)
# …
Как упоминалось в ответе на этот вопрос, можно использовать bleach
.
Начните с определения списка тегов, которые вы хотите разрешить, переопределив стандартные ALLOWED_TAGS
ALLOWED_TAGS = ['br', 'italic', 'strong', 'ul', 'li']
Затем, используйте bleach.clean()
для удаления любых других HTML тегов, которые не разрешены
user_input = '<p>an <strong>example</strong> for SO</p>'
cleaned_user_input = bleach.clean(user_input, tags=ALLOWED_TAGS)
Это удалит тег p
из тега user_input
.