我在这个SO问题中了解到,目前没有简单的方法可以将基于cookie的CSRF令牌转换为Elm中的HTTP请求标头。因此,要编写一个与 Django Rest Framework 后端完美配合的单页应用程序 (SPA),我需要从相应的 cookie 值中手动检索 CSRF-Token。
如何在 Elm 中检索 cookie 值? Elm 是否通过某些命令为此提供运行时支持?或者我是否需要使用纯 JavaScript 检索 cookie 并通过端口将其提供给 ELM SPA?
从 Elm 0.9 开始,您需要使用 Ports 从 JavaScript 读取 cookie 并将其传回 Elm 应用程序。
在我的申请中,我执行以下操作。我定义了一个
fetchCsrfToken
端口,使用 Elm 来调用读取 cookie 的 JavaScript 函数。然后该函数通过 csrfTokenReceiver
端口触发对 Elm 的回调。我的 Elm 应用程序通过订阅来订阅该事件。
-- Ports.elm
port fetchCsrfToken : () -> Cmd msg
port csrfTokenReceiver : (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.csrfTokenReceiver GotCsrfToken
// index.js
app.ports.fetchCsrfToken.subscribe(function (str) {
const value = getCookie('csrftoken')
if (value === null) {
app.ports.csrfTokenReceiver.send('')
} else {
app.ports.csrfTokenReceiver.send(value)
}
})
使用Elm 0.19.1
使用 2 个端口、订阅和一些 JS/TS 代码,如 @viam0Zah 提到的。
在 init 时将 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/,这太棒了!