我最近开始探索Clojure,我想建立一个具有基本CRUD功能的简单Web应用程序。我在这里找到了一个很好的教程:http://www.xuan-wu.com/2013-09-21-Basic-Web-Application-in-Clojure。
GET请求工作正常,但每当我尝试发布请求时,都会收到以下错误:
Invalid anti-forgery token
我之前提到的教程没有解决任何与安全相关的问题。我做了一些挖掘,似乎我错过了Compojure的一些组件,它应该生成一个用于发出POST请求的令牌。有些地方提到我应该自动发生,而我没有任何改变。我仍然不确定我失踪了什么。这是我的代码:
(ns myblog.handler
(:require [compojure.core :refer :all]
[compojure.route :as route]
[ring.middleware.defaults :refer [wrap-defaults site-defaults]]
[myblog.views :as views]
[myblog.posts :as posts]
[ring.util.response :as resp]
[ring.middleware.basic-authentication :refer :all]))
(defn authenticated? [name pass]
(and (= name "user")
(= pass "pass")))
(defroutes public-routes
(GET "/" [] (views/main-page))
(route/resources "/"))
(defroutes protected-routes
(GET "/admin" [] (views/admin-page))
(GET "/admin/add" [] (views/add-post))
(POST "/admin/create" [& params]
(do (posts/create params)
(resp/redirect "/admin"))))
(defroutes app-routes
public-routes
(wrap-basic-authentication protected-routes authenticated?)
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
同样,只有POST请求" / admin / create"失败时出现无效令牌错误。知道我做错了吗?
答案 0 :(得分:23)
您的问题在于wrap-defaults和site-defaults设置。 site-defaults默认配置添加了ant9forgery CSRF保护,任何不包含有效CSRF令牌的post请求都将被阻止。
有几种方法可以解决这个问题。
使用api-defaults而不是site-defaults。 api-defaults默认配置适用于您正在提供Web API的站点以及站点默认值中包含的CSRF保护,这适用于更传统的网站,其中发布请求是由之前已交付的表单生成的通过get请求并将csrf-token包含为隐藏字段。此解决方案的缺点是它还可能禁用您希望包含的其他中间件
在site-default配置中禁用csrf保护。这涉及将地图中的适当键值设置为假,即
eager_load
答案 1 :(得分:3)
请参阅此github example。特别是在底部:
ring-defaults默认包括POST请求的防伪(和 其他修改数据的人。)
如果你不想要这个,我认为你需要改变你对默认值的使用:
wrap-defaults routes site-defaults
如果您不想禁用它,则需要提交带有令牌的隐藏字段的表单,或者通过X-CSRF-Token
和X-XSRF-Token
将其传递到标题中。有关详细信息,请参阅环形中间件docs以获取环形防伪。
答案 2 :(得分:3)
在表单中添加隐藏字段,例如使用enlive-html:
char
或禁用它,不推荐,如:
(def app (wrap-defaults app-routes(assoc-in site-defaults [:security:anti-forgery] false)))