2

我在这个 SO question中了解到,目前没有简单的方法可以将基于 cookie 的 CSRF 令牌转换为 Elm 中的 HTTP 请求标头。因此,要编写与 Django Rest Framework 后端完美配合的单页应用程序 (SPA),我需要从相应的 cookie 值中手动检索 CSRF-Token。

如何在 Elm 中检索 cookie 值?Elm 是否通过某些命令为此提供运行时支持?或者我是否需要使用纯 JavaScript 检索 cookie 并通过端口将其提供给 ELM SPA?

4

2 回答 2

4

从 Elm 0.9 开始,您需要使用Ports从 JavaScript 读取 cookie 并将其传递回 Elm 应用程序。

在我的应用程序中,我执行以下操作。我从 Elm 定义了一个fetchCsrfToken端口,用于调用读取 cookie 的 JavaScript 函数。然后该函数通过csrfTokenReciever端口触发对 Elm 的回调。我的 Elm 应用程序通过订阅订阅该事件。

-- Ports.elm

port fetchCsrfToken : () -> Cmd msg
port csrfTokenReciever : (String -> msg) -> Sub msg
-- Main.elm

init : Flags -> Url -> Key -> ( Model, Cmd Msg )
init flags url key =
  -- ...
  (model, Ports.fetchCsrfToken ())
  

subscriptions : Model -> Sub Msg
subscriptions model =
  Ports.csrfTokenReciever GotCsrfToken
// index.js

app.ports.fetchCsrfToken.subscribe(function (str) {
  const value = getCookie('csrftoken')
  if (value === null) {
    app.ports.csrfTokenReciever.send('')
  } else {
    app.ports.csrfTokenReciever.send(value)
  }
})
于 2021-12-03T18:42:41.530 回答
1

使用榆树 0.19.1

第一个解决方案:

使用2 个端口、一个订阅和一些 JS/TS 代码,例如提到的 @viam0Zah。


第二种解决方案:

在初始化时将 CSRF 传递到您的标志中

    const app = Elm.Main.init({
      node: document.querySelector("main"),
      flags: {
        csrfToken: getCookie('csrftoken')
      }
    });

将 csrfToken 添加到标志

type alias Flags =
    { ---
    , csrfToken : String
    }

并且不要忘记为 csrfToken 添加解码器:

import Json.Decode as D

flagsDecoder : D.Decoder Flags
flagsDecoder =
    D.succeed Flags
        |> ---
        |> D.required "csrfToken" D.string

如果您想为两种解决方案(标志和端口)更健壮并扩展类型安全,您应该查看https://elm-ts-interop.com/,这太棒了!

于 2021-12-24T14:06:30.040 回答