Clojure 默认情况下,Compojure应用程序不发送CSRF
我正在使用试剂和compojure制作一个玩具网络应用程序,我不明白为什么我的服务器没有发送CSRF cookie。其他答案和一些博客文章似乎暗示compojure的默认设置现在发送CSRF令牌,手动重新发送它实际上是一个bug。当我尝试点击POST/art端点时,我得到了403禁止响应。没有一个页面获得包含CSRF令牌的cookie,因此我无法将其与POST请求一起发送。有什么建议吗Clojure 默认情况下,Compojure应用程序不发送CSRF,clojure,csrf,compojure,ring,reagent,Clojure,Csrf,Compojure,Ring,Reagent,我正在使用试剂和compojure制作一个玩具网络应用程序,我不明白为什么我的服务器没有发送CSRF cookie。其他答案和一些博客文章似乎暗示compojure的默认设置现在发送CSRF令牌,手动重新发送它实际上是一个bug。当我尝试点击POST/art端点时,我得到了403禁止响应。没有一个页面获得包含CSRF令牌的cookie,因此我无法将其与POST请求一起发送。有什么建议吗 ;;server.clj (ns my-app.server (:require [my-app.han
;;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上,因为我仍然看不出哪里出了问题。因此我找到了一个相关问题的答案,目前对我来说已经足够好了。我将middleware.clj站点默认值切换为不使用CSRF的api默认值。仍然很好奇如何让CSRF在这里工作,但这对我所做的并不重要。如果有人建议一个有效的修复方法,我会将其标记为正确的 其他答案和一些博客文章似乎暗示compojure的默认设置现在发送CSRF令牌,手动重新发送它实际上是一个bug 包装默认值站点默认值应用中间件。这将只向每个环浏览器会话添加一个CSRF令牌,并在POST请求中查找该令牌。如果令牌丢失,中间件将为请求返回403。将令牌添加到表单或ajax/任何post请求都取决于您,自由的代价是: 从文档中: 默认情况下,令牌应位于名为“_anti-forgery-token”的表单字段中,或位于“X-CSRF-token”或“X-XSRF-token”头中 例如,尝试添加此路由:
(GET "/someform" request (html5 (ring.util.anti-forgery/anti-forgery-field)))
防伪字段助手将添加一个隐藏的输入字段,该字段的值为CSRF令牌,如果表单已发布,则中间件将获取该字段。要直接访问令牌,您可以使用ring.middleware.anti-forgery/*anti-forgery-token*或在当前请求映射的会话中查找它:
(-> request :session :ring.middleware.anti-forgery/anti-forgery-token)
全局变量和辅助对象扩展到处理程序上下文,但不能从外部或同一上下文中的其他线程访问它
简单卷曲头示例:
获取CSRF令牌:
$ curl -v -c /tmp/cookiestore.txt http://localhost:3000/someform
通过标题设置令牌并发布一些内容:
$ curl -v -b /tmp/cookiestore.txt --header "X-CSRF-Token: ->token from prev. req<-" -X POST -d '{:foo "bar"}' localhost:3000/art
请发布wrap中间件的源代码,因为这是解决问题的关键部分。我的印象是CSRF处理是在wrap defaults站点defaults中完成的,但这种印象似乎是错误的。非常感谢您的指导:wrap默认值确实处理CSRF:您使用的是什么版本?compojure 1.4.0;刚刚更新到1.5.0,但没有解决问题。环默认值的版本是什么?包裹默认值就在那里。