无法在Clojure中完成POST请求

无法在Clojure中完成POST请求,post,clojure,compojure,antiforgerytoken,Post,Clojure,Compojure,Antiforgerytoken,我最近开始探索Clojure,我想建立一个具有基本CRUD功能的简单web应用程序。我在这里找到了一个不错的教程: GET请求工作正常,但每当我尝试post请求时,都会出现以下错误: Invalid anti-forgery token 我前面提到的教程没有涉及任何与安全相关的内容。我做了一些深入的研究,似乎我缺少了Compojure的一些组件,这些组件应该生成一个令牌来发出POST请求。有些地方提到,我应该在没有任何改变的情况下自动发生。我仍然不确定我错过了什么。这是我的密码: (ns my

我最近开始探索Clojure,我想建立一个具有基本CRUD功能的简单web应用程序。我在这里找到了一个不错的教程:

GET请求工作正常,但每当我尝试post请求时,都会出现以下错误:

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”失败,出现无效令牌错误。知道我做错了什么吗?

看看这个github。尤其是在底部:

环默认值包括POST请求的默认防伪(和 修改数据的其他人)

我认为,如果您不希望这样做,您需要更改默认值的使用:

wrap-defaults routes site-defaults

如果不想禁用它,则需要提交一个带有标记的隐藏字段的表单,或者通过
X-CSRF-token
X-XSRF-token
将其传递到标题中。有关详细信息,请参阅戒指防伪中间件。

您的问题在于包装默认值和站点默认值设置。站点默认配置添加了ant9forgery CSRF保护,任何不包含有效CSRF令牌的post请求都将被阻止

有几种方法可以解决这个问题

  • 使用api默认值而不是站点默认值。api defaults默认配置适用于提供web api和站点默认设置中包含的CSRF保护的站点,这适用于更传统的网站,其中post请求由以前通过get请求交付的表单生成,并将CSRF令牌包含为隐藏字段。此解决方案的缺点是,它还可能禁用您希望包含的其他中间件

  • 在站点默认配置中禁用csrf保护。这涉及将映射中的相应键值设置为false,即
    (包装默认应用程序路由(网站默认设置中的assoc[:安全:防伪]false))


  • 在表单中添加隐藏字段,例如使用enlive html:

    (ns xxx.html
      (:use [net.cgrand.enlive-html])
      (:require [clojure.string :as str]
                [ring.util.anti-forgery :refer [anti-forgery-field]]))
    
    (deftemplate render-page "base.html"
      [settings]
      [:form#my-form] (append (html-snippet (anti-forgery-field)))
      ...
    )
    
    或禁用它,不推荐,因为:

    (def应用程序
    (包装默认应用程序路由(网站默认设置中的assoc[:security:anti-forgery]false))

    您是如何发出POST请求的?类似于浏览器中的
    curl
    或在浏览器中。我正在向/admin/create提交表单。如果您使用Selmer,则在模板中添加隐藏字段的代码将是
    {{anti-forgery field | safe}}
    ,其中:anti-forgery field是数据映射中的一个键。