在 Clojure/Compojure 中转义/清理用户输入

Posted

技术标签:

【中文标题】在 Clojure/Compojure 中转义/清理用户输入【英文标题】:Escape/sanitize user input in Clojure/Compojure 【发布时间】:2011-02-23 06:21:42 【问题描述】:

我正在使用 Clojure/Ring/Compojure-0.4/Enlive 堆栈构建 Web 应用程序。

此堆栈中是否有函数可以去除用户提供的 html 或 HTML 编码(即 <a><a>)字符串以防止 XSS 攻击?

【问题讨论】:

【参考方案1】:

hiccup.util/escape-html in hiccup 做到了。该功能曾经在 Compojure 本身中(因为 hiccup 中的所有功能曾经是 Compojure 的一部分)。这是一个足够简单的函数,您可以轻松地自己编写它。

(defn escape-html
  "Change special characters into HTML character entities."
  [text]
  (.. #^String (as-str text)
    (replace "&" "&")
    (replace "<" "&lt;")
    (replace ">" "&gt;")
    (replace "\"" "&quot;")))

还有clojure.contrib.string/escape,它采用char -> 字符串转义序列的映射和一个字符串并为您转义它。

user> (clojure.contrib.string/escape \< "&lt;" \> "&gt;" "<div>foo</div>")
"&lt;div&gt;foo&lt;/div&gt;"

这让我觉得它可能没有那么有用,因为您可能想要转义多字符序列,而这不会让您这样做。但它可能适用于您的 HTML 转义需求。

当然,还有很多 Java 库可以做到这一点。您可以使用来自 Apache Commons 的 StringEscapeUtils:

(org.apache.commons.lang.StringEscapeUtils/escapeHtml4 some-string)

不过,这让我觉得有点重量级。

【讨论】:

StringEscapeUtils commons.apache.org/lang/api-release/org/apache/commons/lang/…的正确URL 更新网址commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/…【参考方案2】:

更新:我知道肯定不止这些......

来自ring-corering.util.codec 有一个名为的函数,其工作方式如下:

user> (require '[ring.util.codec :as c])
nil
user> (c/url-encode "<a>")
"%3Ca%3E"
user> (c/url-decode "<a>")
"<a>"

这些是 java.net.URLEncoderjava.net.URLDecoder 的包装。相同的命名空间提供了处理 Base64 编码的函数,基于 Apache Commons 的一个类。


原答案如下。

我不确定是否有公共函数可以执行此操作,但 Enlive 有两个私有函数,分别称为 xml-strattr-str

(defn- xml-str
 "Like clojure.core/str but escapes < > and &."
 [x]
  (-> x str (.replace "&" "&amp;") (.replace "<" "&lt;") (.replace ">" "&gt;")))

attr-str 也转义了"。)

您可以使用 @#'net.cgrand.enlive-html/xml-str 获得该功能(Clojure 并不倾向于将事物真正设为私有...),或者只是将其复制到您自己的命名空间。

【讨论】:

这有点令人失望。在大多数 Clojure Web 框架中,这听起来像是一个重大疏忽。 显然情况并没有那么糟糕:请参阅更新后的答案。 :-) 看来我责怪 Enlive 有点仓促,但还是谢谢你。 :) URL 编码确实不同于 HTML 编码。 url-encode("") => "%3Ca%3E" 其中 html-encode("") => "<a>" 悉达多·雷迪:对。我似乎忘记了发布原始答案和进行编辑之间的规范——感谢您指出。至少这两个选项确实使用户输入安全。 (叹气) 不管怎样,xml-str 确实使用了&amp;foo; 实体;太糟糕了,它是私人的。当然,Brian 的回答确实最适合上述问题。【参考方案3】:

如果您使用net.cgrand.enlive-html/content 将文本放入 HTML 元素,Enlive 默认会转义 HTML。

(sniptest "<p class=\"c\"></p>" [:.c] (content "<script></script>"))
"<p class=\"c\">&lt;script&gt;&lt;/script&gt;</p>"

【讨论】:

以上是关于在 Clojure/Compojure 中转义/清理用户输入的主要内容,如果未能解决你的问题,请参考以下文章

在 NVelocity 中转义 "

如何在 Presto 中转义单引号?

为啥必须在 XML 属性中转义 <?

在 Apache Ant 中转义斜线

如何在 MySql 中转义撇号(')?

在速度模板中转义引号