开发者

Escape/sanitize user input in Clojure/Compojure

I am using Clojure/Ring/Compojure-0.4/Enlive stack开发者_运维技巧 to build a web application.

Are there functions in this stack that would either strip HTML or HTML-encode (i.e. <a> to &lt;a&gt;) user-supplied strings in order to prevent XSS attacks?


hiccup.util/escape-html in hiccup does it. That function used to be in Compojure itself (since all of the functionality in hiccup used to be part of Compojure). It's a simple enough function that you could easily write it yourself though.

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

There's also clojure.contrib.string/escape, which takes a map of char -> string escape sequences and a string and escapes it for you.

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

This strikes me as not as useful as it could be, because you might want to escape multi-character sequences and this won't let you. But it might work for your HTML-escaping needs.

And then there are many Java libraries for this, of course. You could use StringEscapeUtils from Apache Commons:

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

This strikes me as a bit heavyweight for this purpose though.


Update: I knew there had to be more than that...

ring.util.codec from ring-core has a functions called which work like so:

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

These are wrappers around java.net.URLEncoder and java.net.URLDecoder. The same namespace provides functions for dealing with Base64 encoding, based on a class from Apache Commons.


Original answer follows.

I'm not sure whether there is a public function to do this, but Enlive has two private functions called xml-str and attr-str which do this:

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

(attr-str also escapes ".)

You could get at that function with @#'net.cgrand.enlive-html/xml-str (Clojure doesn't tend to make things really private...) or just copy it to your own namespace.


It turns out Enlive does escape HTML by default if you use net.cgrand.enlive-html/content to put text into a HTML element.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜