Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added a slot "one-time-p" to Clack.Middleware.Csrf, and changed it no…

…t to remove CSRF-token after valid POST by default.
  • Loading branch information...
commit a7d75e953d90b1f49043ecf3802d860690026dde 1 parent 22c8d11
@fukamachi authored
Showing with 46 additions and 13 deletions.
  1. +7 −2 src/contrib/middleware/csrf.lisp
  2. +39 −11 t/contrib/middleware/csrf.lisp
View
9 src/contrib/middleware/csrf.lisp
@@ -23,7 +23,11 @@
((block-app :initarg :block-app
:type (or function <component>)
:initform #'return-400
- :accessor block-app))
+ :accessor block-app)
+ (one-time-p :initarg :one-time-p
+ :type boolean
+ :initform nil
+ :accessor one-time-p))
(:documentation "Clack Middleware for easy CSRF protection."))
(defmethod call ((this <clack-middleware-csrf>) env)
@@ -36,7 +40,8 @@
(if (valid-token-p env)
(progn
;; delete onetime token
- (remhash :csrf-token (getf env :clack.session))
+ (when (one-time-p this)
+ (remhash :csrf-token (getf env :clack.session)))
(call-next this env))
(call (block-app this) env)))
View
50 t/contrib/middleware/csrf.lisp
@@ -102,17 +102,7 @@
:cookie-jar cookie-jar)
(is status 200 "Status is 200")
(is (cdr (assoc :content-type headers)) "text/html" "Content-Type is text/html")
- (is body "Eitarow Fukamachi" "can read body-parameter"))
- (diag "bad POST request with before token")
- (multiple-value-bind (body status headers)
- (http-request "http://localhost:4242/"
- :method :post
- :parameters `(("name" . "Eitarow Fukamachi")
- ("_csrf_token" . ,csrf-token))
- :cookie-jar cookie-jar)
- (declare (ignore body))
- (is status 400 "Status is 400")
- (is (cdr (assoc :content-type headers)) "text/plain" "Content-Type is text/plain")))))
+ (is body "Eitarow Fukamachi" "can read body-parameter")))))
(setf app
(builder <clack-middleware-session>
@@ -139,4 +129,42 @@
(is (cdr (assoc :location headers)) "http://en.wikipedia.org/wiki/CSRF")
(is body nil))))
+(setf app
+ (builder <clack-middleware-session>
+ (<clack-middleware-csrf> :one-time-p t)
+ #'(lambda (env)
+ (let ((req (make-request env)))
+ `(200
+ (:content-type "text/html")
+ (,(if (and (eq :post (request-method req))
+ (body-parameter req :|name|))
+ (body-parameter req :|name|)
+ (html-form env))))))))
+
+(diag "Enable one-time token")
+(test-app
+ app
+ #'(lambda ()
+ (let (csrf-token
+ (cookie-jar (make-instance 'cookie-jar)))
+ (setf csrf-token
+ (parse-csrf-token
+ (http-request "http://localhost:4242/"
+ :cookie-jar cookie-jar)))
+ (http-request "http://localhost:4242/"
+ :method :post
+ :parameters `(("name" . "Eitarow Fukamachi")
+ ("_csrf_token" . ,csrf-token))
+ :cookie-jar cookie-jar)
+ (diag "bad POST request with before token")
+ (multiple-value-bind (body status headers)
+ (http-request "http://localhost:4242/"
+ :method :post
+ :parameters `(("name" . "Eitarow Fukamachi")
+ ("_csrf_token" . ,csrf-token))
+ :cookie-jar cookie-jar)
+ (declare (ignore body))
+ (is status 400 "Status is 400")
+ (is (cdr (assoc :content-type headers)) "text/plain" "Content-Type is text/plain")))))
+
(finalize)
Please sign in to comment.
Something went wrong with that request. Please try again.