#ruby-on-rails #strip-tags
#ruby-on-rails #strip-теги
Вопрос:
Мне нужно удалить теги из пользовательского ввода перед сохранением в БД
Я хорошо знаком с методом strip_tags, но он также экранирует строку html, как и все другие рекомендуемые методы:
Rails::Html::FullSanitizer.new.sanitize 'amp;'
=> "amp;amp;"
Rails::Html::WhiteListSanitizer.new.sanitize('amp;', tags: [])
=> "amp;amp;"
ActionController::Base.helpers.strip_tags "amp;"
=> "amp;amp;"
Строка, которую я хочу очистить, НЕ должна экранироваться, она экспортируется через API, используется в файлах и т. Д. он выводится не только через HTML (где также в таких случаях, как link_to ActionController::Base.helpers.strip_tags("amp;")
— link_to — двойная экранирующая строка, поэтому вы получите ссылку amp;amp;
на интерфейс)
В качестве исправления для обезьян я включил strip_tags, CGI.unescapeHTML
чтобы получить более или менее ожидаемый результат, но хочу найти какое-то прямое решение (я также боюсь, что еще может сделать strip_tags, и для этой небольшой функциональности слишком много движущихся частей — больше вещей, которые могут пойти не так или сломаться)
Пример реального мира: JPMorgan Chase amp; Co
должен стать JPMorgan Chase amp; Co
после удаления тегов
test<script>alert('hacked!');</script>amp;test
должно стать testamp;test
после удаления тегов
А также строка:
"test amp;#x3C;scriptamp;#x3E;alert(amp;#x27;hacked!amp;#x27;)amp;#x3C;/scriptamp;#x3E;"
Все равно должно быть
"test amp;#x3C;scriptamp;#x3E;alert(amp;#x27;hacked!amp;#x27;)amp;#x3C;/scriptamp;#x3E;"
После удаления HTML’ов
С альтернативными решениями, которые я нашел или которые были предложены:
> Nokogiri::HTML("test amp;#x3C;scriptamp;#x3E;alert(amp;#x27;hacked!amp;#x27;)amp;#x3C;/scriptamp;#x3E;").text
=> "test <script>alert('hacked!')</script>"
> Loofah.fragment("test amp;#x3C;scriptamp;#x3E;alert(amp;#x27;hacked!amp;#x27;)amp;#x3C;/scriptamp;#x3E;").text(encode_special_chars: false)
=> "test <script>alert('hacked!')</script>"
Так что они тоже не подходят
Комментарии:
1. Можете ли вы привести пример рассматриваемой строки и желаемого результата?
2. Я обновил информацию на примере реального мира
Ответ №1:
Вы должны проанализировать HTML и извлечь текстовые элементы. Для этого используйте Nokogiri.
Nokogiri::HTML("<div>Strip <i>this</i> amp; <b>this</b> amp; <u>this</u>!</div>").text
Nokogiri уже используется Rails, поэтому его использование не требует затрат.
Вы получите весь текст, включая содержимое <script>
тегов.
Nokogiri::HTML(%q[test<script>alert('hacked!');</script>amp;test]).text
# testalert('hacked!');amp;test
Вы можете удалить <script>
теги.
doc = Nokogiri::HTML(%q[test<script>alert('hacked!');</script>amp;test])
doc.search('//script').each { |node| node.replace('') }
doc.text
# testamp;test
Но с удаленными тегами строка не причинит вреда. Возможно, это не стоит затраченных усилий.
Подробнее см. В уроках Nokogiri.
Комментарии:
1. О, это именно то, что я искал! Спасибо!
2. Ах, нет, извините, это не сработает: (См. Мое обновление внизу вопроса
3. @HandsomeJack Каков ваш конечный результат? Защищаете ли вы от внедрения HTML? Или вы извлекаете текст из HTML? Похоже, что и то, и другое. Это разные вещи. Если оба, извлеките текст, а затем экранируйте любой HTML, который мог скрываться в тексте. Но вы уже должны экранировать свой текст перед его использованием, а не при его сохранении; таким образом, вы не догадываетесь, как он будет использоваться. Извлеките текст, сохраните его в базе данных. Затем вы можете использовать его для чего угодно. Затем экранируйте любой текст, прежде чем поместить его в HTML, не думайте, что он уже экранирован.