Как безопасно обрабатывать пользовательский ввод в Unicode в Scala (особенно в XML-сущностях)
На моем веб-сайте есть форма, в которой вводятся текстовые данные пользователя. Все отлично работает для "нормальных" персонажей. Однако, когда вводятся символы Юникода... ну, сюжет утолщается.
Пользователь вводит что-то вроде
やっぱ死にかけてる
Это приходит на сервер как текст, содержащий ссылки на сущность XML
やっぱ死にかけてる?
Теперь, когда я хочу передать это обратно клиенту в HTML, как мне это сделать?
Если я просто выведу строку в том виде, в каком она есть, может возникнуть вероятность атаки скриптом. Если я попытаюсь закодировать это scala.xml.Text
он преобразуется в:
やっぱ死にかけてる?
Есть ли лучшее готовое решение в Scala, которое может обнаруживать ссылки на сущности и не избегать их, но избегать тегов XML?
4 ответа
Разобрать строку, содержащую ссылки на сущности, как фрагмент XML. Чтобы безопасно выводить символы Unicode в XML, вы можете быть параноиком и использовать для них ссылки на сущности XML согласно функции escape
scala>import xml.parsing.ConstructingParser
import xml.parsing.ConstructingParser
scala>import io.Source
import io.Source
scala> val d = ConstructingParser.fromSource(Source.fromString("<dummy>や</dummy>"), true).documnent
d: scala.xml.Document = <dummy>や</dummy>
scala>val t = d(0).text
res0: String = や
scala> import xml._
import xml._
scala> def escape(xmlText: String): NodeSeq = {
| def escapeChar(c: Char): xml.Node =
| if (c > 0x7F || Character.isISOControl(c))
| xml.EntityRef("#" + Integer.toString(c, 10))
| else
| xml.Text(c.toString)
|
| new xml.Group(xmlText.map(escapeChar(_)))
| }
escape: (xmlText: String)scala.xml.NodeSeq
scala> <foo>{escape(t)}</foo>
res3: scala.xml.Elem = <foo>や</foo>
Хорошо, я пытаюсь этот простой взломать. Комментарии приветствуются:
def secureEscape(text: String) = {
val s = new StringBuilder()
for (c <- text.elements) c match {
case '<' => s.append("<")
case '>' => s.append(">")
case _ => s.append(c)
}
s.toString
}
Это в основном сбежать <
а также >
,
Затем я использую эту функцию, чтобы проанализировать входящие данные формы и затем передать их без дальнейшей обработки клиенту.
Действительно, браузер должен отвечать за правильную кодировку UTF-8 и экранирование символов (это, кажется, происходит). Ваш веб-фреймворк должен затем обрабатывать удаление и декодирование.
Это может быть сложный бизнес, включающий несколько этапов, каждый из которых может быть явно настроен для корректной работы UTF-8. Особенно при работе со старыми платформами и серверами, кеширующими прокси, сетями доставки контента и т. Д.
Дело в том, что внутри вы хотите видеть ожидаемые символы Юникода, а не ссылки на сущности. Точно так же вы должны выводить собственный юникод и обрабатывать требуемое кодирование на границе вашей системы, предпочтительно это будет автоматически обрабатываться вашим выбором веб-фреймворка.
Чтобы дать вам правильное решение, необходимо знать, какой программный стек (ы) вы используете и как отправляется форма (т.е. GET/POST/AJAX+JSON)
Браузеры кодируют входные символы только в числовые ссылочные объекты, когда этот символ находится за пределами набора символов, в котором была обслужена страница. Избавьте себя от множества проблем и обслуживайте свои страницы в UTF-8, правильно помеченном как UTF-8. Обработка строк в Scala, Java и Javascript выполняется в Юникоде, и ограничение iso-8859-1 для ваших веб-страниц вызывает проблемы с преобразованием, подобные этой, во всех направлениях. Если ваш существующий контент - ASCII, тогда преобразование должно быть безболезненным