2016-03-07 9 views
1

Я использую реагент и compojure, чтобы сделать игрушку webapp, и я не могу понять, почему мой сервер не отправляет cookie CSRF. Другие ответы и несколько сообщений в блоге, по-видимому, подразумевают, что настройки по умолчанию для compojure теперь отправляют токен CSRF и что пересылка вручную на самом деле является ошибкой. Когда я пытаюсь попасть в конечную точку POST /art, я возвращаю запретный ответ 403. Ни одна из страниц не получает cookie с токеном CSRF, поэтому я не могу отправить его с запросом POST. Любой совет?Приложение Compojure не отправляет CSRF по умолчанию

;;server.clj 

(ns my-app.server 
    (:require [my-app.handler :refer [app]] 
      [environ.core :refer [env]] 
      [ring.adapter.jetty :refer [run-jetty]]) 
    (:gen-class)) 

(defn -main [& args] 
    (let [port (Integer/parseInt (or (env :port) "3000"))] 
    (run-jetty app {:port port :join? false}))) 

;; handler.clj 

(ns my-app.handler 
    (:require [compojure.core :refer [GET POST defroutes]] 
      [compojure.route :refer [not-found resources]] 
      [hiccup.page :refer [include-js include-css html5]] 
      [my-app.middleware :refer [wrap-middleware]] 
      [environ.core :refer [env]])) 


(defroutes routes 
    (GET "/" [] loading-page) 
    (GET "/about" [] loading-page) 
    (GET "/art" [] loading-page) 
    (POST "/art" request {:sent (:body request) :hello "world"}) 

    (resources "/") 
    (not-found "Not Found")) 

(def app (wrap-middleware #'routes)) 


;;middleware.clj 

(ns stagistry.middleware 
    (:require [ring.middleware.defaults :refer [site-defaults wrap-defaults]] 
      [prone.middleware :refer [wrap-exceptions]] 
      [ring.middleware.reload :refer [wrap-reload]])) 

(defn wrap-middleware [handler] 
    (-> handler 
     (wrap-defaults site-defaults) 
     wrap-exceptions 
     wrap-reload)) 

Я бросил сам код на GitHub here, так как я до сих пор не может видеть то, что случилось.

+1

Пожалуйста, разместите источник для 'wrap-middleware', поскольку это ключевая часть вашей проблемы. –

+0

Мое впечатление, что обработка CSRF выполнялась в '(wrap-defaults site-defaults)', но это впечатление кажется неправильным. Руководство будет принята с благодарностью :) – BWStearns

+1

'wrap-defaults' действительно обрабатывает CSRF: https://github.com/ring-clojure/ring-defaults/blob/master/src/ring/middleware/defaults.clj#L91 что версию вы используете? – OlegTheCat

ответ

0

Другие ответы и несколько сообщений в блоге, по-видимому, подразумевают, что настройки по умолчанию для compojure теперь отправляют токен CSRF и что его пересылка вручную является на самом деле ошибкой.

(wrap-defaults site-defaults) применяет промежуточное программное обеспечение ring-anti-forgery. Это добавит токен CSRF в каждый сеанс браузера обозревателя и будет искать токен в POST-запросах. Если токен отсутствует, промежуточное программное обеспечение вернет 403 для запроса. Добавление маркера в вашу форму или ajax/любые запросы по почте зависит от вас, цена свободы. :)

Из ring-anti-forgery документов:

По умолчанию, маркер, как ожидается, будет в поле формы с именем «__anti-подделкой лексемы» или в «X-CSRF-токене» или Заголовки X-XSRF-Token.

Например попробуйте добавить этот маршрут:

(GET "/someform" request (html5 (ring.util.anti-forgery/anti-forgery-field))) 

Помощник anti-forgery-field будет добавить скрытое поле ввода с маркером CSRF в качестве значения, которое поднято промежуточного, если форма размещена. Чтобы получить доступ к фишке непосредственно вы можете использовать либо ring.middleware.anti-forgery/*anti-forgery-token* или посмотреть его в сессии текущей карты запроса:

(-> request :session :ring.middleware.anti-forgery/anti-forgery-token) 

Глобальные переменное (и расширение хелперного) является bound в контекст обработчика, хотя, вы можете 'получить доступ к нему извне или из другого потока в том же контексте.

Простой пример локон Заголовок:

  1. Получить маркер CSRF:

    $ curl -v -c /tmp/cookiestore.txt http://localhost:3000/someform 
    

  2. Установите маркер через заголовок и опубликовать некоторые вещи:

    $ curl -v -b /tmp/cookiestore.txt --header "X-CSRF-Token: ->token from prev. req<-" -X POST -d '{:foo "bar"}' localhost:3000/art 
    
0

Итак, я нашел ответ на соответствующий вопрос, который достаточно хорош для меня на данный момент. Я переключил middleware.clj site-defaults на api-defaults, который не использует CSRF. Все еще любопытно, как сделать CSRF здесь, но это не критично для того, что я делаю. Если кто-либо из последних предлагает исправить это, я буду отмечать это как правильное.