add support for automatically including anti-forgery tokens in POST reqs

This commit is contained in:
Gered 2014-12-27 18:10:32 -05:00
parent 88a212316a
commit a0fd9b1f8c
3 changed files with 26 additions and 8 deletions

View file

@ -7,7 +7,8 @@
:dependencies [[org.clojure/clojure "1.6.0"] :dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/clojurescript "0.0-2371" :scope "provided"] [org.clojure/clojurescript "0.0-2371" :scope "provided"]
[org.clojure/core.async "0.1.346.0-17112a-alpha"] [org.clojure/core.async "0.1.346.0-17112a-alpha"]
[net.thegeez/clj-browserchannel-server "0.1.0"]] [net.thegeez/clj-browserchannel-server "0.1.0"]
[prismatic/dommy "1.0.0"]]
:source-paths ["target/generated/src/clj" "src/clj"] :source-paths ["target/generated/src/clj" "src/clj"]
:resource-paths ["target/generated/src/cljs" "src/cljs"] :resource-paths ["target/generated/src/cljs" "src/cljs"]

View file

@ -1,9 +1,10 @@
(ns clj-browserchannel-messaging.server (ns clj-browserchannel-messaging.server
(:refer-clojure :exclude [send]) (:refer-clojure :exclude [send])
(:require [clojure.edn :as edn] (:require
[clojure.core.async :refer [chan pub sub <! put! go-loop]] [clojure.edn :as edn]
[net.thegeez.browserchannel :as browserchannel] [clojure.core.async :refer [chan pub sub <! put! go-loop]]
[clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]])) [net.thegeez.browserchannel :as browserchannel]
[clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]]))
(defonce ^:private handler-middleware (atom nil)) (defonce ^:private handler-middleware (atom nil))

View file

@ -1,10 +1,12 @@
(ns clj-browserchannel-messaging.client (ns clj-browserchannel-messaging.client
(:require-macros [cljs.core.async.macros :refer [go-loop]]) (:require-macros
[cljs.core.async.macros :refer [go-loop]])
(:require (:require
[cljs.reader :as reader] [cljs.reader :as reader]
[cljs.core.async :refer [pub sub chan <! put!]] [cljs.core.async :refer [pub sub chan <! put!]]
goog.net.BrowserChannel goog.net.BrowserChannel
[goog.events :as events] [goog.events :as events]
[dommy.core :refer-macros [sel1]]
[clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]])) [clj-browserchannel-messaging.utils :refer [run-middleware get-handlers encode-message decode-message]]))
(defonce ^:private handler-middleware (atom nil)) (defonce ^:private handler-middleware (atom nil))
@ -105,6 +107,9 @@
:on-receive (get-handlers middleware :on-receive) :on-receive (get-handlers middleware :on-receive)
:on-send (get-handlers middleware :on-send)})) :on-send (get-handlers middleware :on-send)}))
(defn- get-anti-forgery-token []
(.-content (sel1 "meta[name='anti-forgery-token']")))
(defn init! (defn init!
"Sets up browserchannel for use, creating a handler with the specified "Sets up browserchannel for use, creating a handler with the specified
properties. this function should be called once on page load. properties. this function should be called once on page load.
@ -160,9 +165,18 @@
receives 1 argument: the message that was received. note that this event is receives 1 argument: the message that was received. note that this event is
only raised for messages which can be decoded by decode-message. also note only raised for messages which can be decoded by decode-message. also note
that this event is raised for all messages received, regardless of any that this event is raised for all messages received, regardless of any
listeners created via message-handler." listeners created via message-handler.
CSRF Anti-Forgery Tokens
If the page contains a <meta> tag with a name of 'anti-forgery-token',
the value of this meta tag will be automatically included under the
X-CSRF-Token HTTP header on all BrowserChannel POST requests to work with
any CSRF protection your web app uses (e.g. Ring's wrap-anti-forgery
middleware)."
[& {:keys [base middleware]}] [& {:keys [base middleware]}]
(let [base (or base "/browserchannel")] (let [base (or base "/browserchannel")
anti-forgery-token (get-anti-forgery-token)]
(register-middleware! middleware) (register-middleware! middleware)
(events/listen (events/listen
js/window "unload" js/window "unload"
@ -173,6 +187,8 @@
; this seems to help prevent premature session timeouts from occuring (vs the default of 3) ; this seems to help prevent premature session timeouts from occuring (vs the default of 3)
(set! goog.net.BrowserChannel/BACK_CHANNEL_MAX_RETRIES 20) (set! goog.net.BrowserChannel/BACK_CHANNEL_MAX_RETRIES 20)
(.setHandler browser-channel (->handler)) (.setHandler browser-channel (->handler))
(if anti-forgery-token
(.setExtraHeaders browser-channel (js-obj "X-CSRF-Token" anti-forgery-token)))
(.connect browser-channel (.connect browser-channel
(str base "/test") (str base "/test")
(str base "/bind")))) (str base "/bind"))))