0

我有以下设置:

  1. 后端的Macchiato框架(即 node.js 上的 ClojureScript),它对 Ring 上的处理进行建模。
  2. 前端由一个小型 React App 组成,用于编辑存储在 atom 中的数据(跟踪各种输入)。

我想通过将其发布到后端的处理程序来使存储在该原子中的数据持久化。最直接的方法似乎只是直接从原子中获取数据并执行以下操作:

(http/post "https://post.here.url"
                                {:edn-params
                                 @my-atom})

但是:默认情况下,Macchiato 要求 POST 请求包含防伪令牌(我目前将其作为属性存储到我的 HTML 元素之一;如果这是不好的做法,请告诉我)。所以我尝试了以下方法:

(http/post "https://post.here.url"
                                {:edn-params
                                 {:data @my-atom
                  :__anti-forgery-token "SuperSecretToken"}})

但是,这不起作用,因为令牌被视为无效而被拒绝。仅当我将数据声明为 :form-params: 时,防伪令牌似乎才被正确处理:

(http/post "https://post.here.url"
                                {:form-params
                                 {:data (str @my-atom)
                  :__anti-forgery-token "SuperSecretToken"}})

上面的方法确实有效,但是,当然,MIME 类型设置不正确,我必须做一些呼啦圈才能使 EDN 数据在服务器端可用。这种方法似乎确实是错误的。有没有办法正确序列化 EDN 数据并仍然传输防伪令牌?

我对这些东西还是很陌生,所以也许我缺少一些基本的东西。我对防伪令牌的一般用途有误吗?仅在传输表单数据时才有意义(我的数据实际上是;只是直接发布原子会使重新加载存储的数据更容易)。

非常感谢您给我的任何意见!

奥利弗

4

1 回答 1

1

现在要弄清楚文档的设置方式有点棘手,但这里有 3 条有用的信息:

  1. https://macchiato-framework.github.io/api/core/macchiato.middleware.anti-forgery.html
  2. https://github.com/macchiato-framework/macchiato-core/blob/master/src/macchiato/middleware/defaults.cljs#L83
  3. https://macchiato-framework.github.io/docs/restful-middleware.html

如果你使用wrap-defaults中间件包装器,你可以传入一个选项值,它要么是真实的(启用你观察到的默认防伪行为),要么是一个选项映射,[1] 中的文档说它带有一个可选:read-token函数。

放在一起,加上rest-middleware[3] 中的内容,这是实现接受默认(表单参数)或 json 有效负载(body-params)的防伪检查的一种方法:

(-> handler
    ;; note: the wrapped middleware request processing
    ;; is handled _bottom-up_ in this chain
    (defaults/wrap-defaults
     (-> defaults/site-defaults
         (assoc-in [:security :anti-forgery]
                   {:read-token (fn [request]
                                  (or
                                   ;; check the custom key we set upstream (but in the block below)
                                   (get-in request [:anti-forgery-payload])
                                   ;; default behavior
                                   (anti-forgery/default-request-token request)))})))
    (middleware/wrap
     (fn extract-anti-forgery-payload [handler]
       (fn [request respond raise]
         (handler
          (if-let [anti-forgery-payload
                   (get-in request [:body "__anti-forgery-token"])]
            (-> request
                ;; add our custom anti-forgery key to the request
                (assoc :anti-forgery-payload anti-forgery-payload)
                ;; remove the special key from the request to downstream handlers
                (update :body dissoc "__anti-forgery-token"))
            request)
          respond raise)))
     {})
    ;; decodes the json input into maps
    (macchiato.middleware.restful-format/wrap-restful-format))
于 2020-09-29T07:26:14.883 回答