在我的网站上,我有一个表单,其中包含一些文本用户输入。一切都适用于“普通”字符。但是当输入unicode字符时......好吧,情节会变粗。
用户输入类似
的内容やっぱ死にかけてる
这作为包含XML实体引用
的文本进入服务器やっぱ死にかけてる?
现在,当我想以HTML格式回复客户端时,我该怎么做?
如果我只是按原样输出字符串,则可能存在脚本攻击的可能性。如果我尝试使用scala.xml.Text
对其进行编码,则会转换为:
やっぱ死にかけてる?
Scala中是否有更好的现成解决方案,可以检测实体引用,不转义它们,但是转义XML标记?
答案 0 :(得分:5)
将包含实体引用的字符串解析为XML片段。要安全地在XML中输出Unicode字符,您可以偏执并使用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>
答案 1 :(得分:1)
好的,我正在尝试这个简单的黑客攻击。欢迎评论:
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
}
这基本上会逃脱<
和>
。
然后我使用此函数来解析传入的表单输入,然后将其输出,而无需进一步处理客户端。
答案 2 :(得分:0)
实际上,浏览器应该负责正确的UTF-8编码和字符转义(这似乎正在发生)。然后,您的Web框架应该处理unescaping和解码。
这可能是一个棘手的业务,涉及几个步骤,所有这些都可能必须明确配置为正确的UTF-8操作。特别是在使用旧框架和服务器,缓存代理,内容交付网络等时
关键是,在内部,您希望看到预期的unicode字符 - 而不是实体引用。同样,您应该在系统边界输出本机unicode和句柄以及所需的编码,最好由您选择的Web框架自动处理。
为了给您正确的解决方案,有必要知道您正在使用的软件堆栈以及表单的提交方式(即GET / POST / AJAX + JSON)
答案 3 :(得分:0)
当字符位于提供页面的字符集之外时,浏览器仅将输入字符编码为数字字符引用实体。节省很多麻烦,并以UTF-8正确标记为UTF-8的方式提供页面。 Scala,Java和Javascript字符串处理全部使用Unicode,并且限制为网页的iso-8859-1会在所有方向上引发这样的转换问题。如果您现有的内容是ASCII,那么转换应该是轻松的。