CSRF:Yesod runFormPost总是FormFailure

时间:2015-08-01 18:57:26

标签: haskell csrf yesod

提前为代码转储道歉。我对Yesod和Haskell都很陌生,而且我正在努力解决CSRF问题。我理解的问题是表单_token与环境令牌不匹配(运行runFormPostNoToken的工作正常)。我有一对路线:

/           HomeR      GET
/upload     UploadR    POST

HomeR的处理程序定义如下:

getHomeR :: Handler Html
getHomeR = do
    ((res, uploadWidget), enctype) <- runFormPost imgForm
    setTitle "Title"
    $(widgetFile "homepage")

表单本身和上传处理程序是:

imgForm :: Html -> MForm (HandlerT App IO) (FormResult Img, Widget) 
imgForm hiddenInput = do
    (titleRes, titleView)   <- mreq textField uploadFormTitleSettings Nothing
    (descRes, descView)     <- mopt textareaField uploadFormDescriptionSettings Nothing
    (fileRes, fileView)     <- mreq fileField uploadFormAttachmentSettings Nothing

    let imgRes =  Img
              <$> titleRes
              <*> descRes
              <*> fileRes
              <*> pure (Likes 0)
              <*> pure (Dislikes 0) 
              <*> pure (UserID 1) 
              <*> pure (Community 1) 

    let imgUploadWidget = do
                      toWidget
                          [whamlet|
                              ^{ fvInput titleView }
                              ^{ fvInput descView }
                              ^{ fvInput fileView }
                              #{ hiddenInput }
                              <button type="submit">Submit
                          |]

    return (imgRes, imgUploadWidget)

postImgUploadR :: HandlerT App IO Html
postImgUploadR = do
    ((imgRes, imgUploadWidget), enctype) <- runFormPost imgForm
    let submission :: HandlerT App IO Html
        submission = case imgRes of
            FormSuccess upload -> defaultLayout [whamlet|The form was uploaded|]
            FormMissing -> defaultLayout [whamlet|The form is missing|]
            FormFailure upload -> defaultLayout [whamlet|The form failed.|]
    submission

不幸的是,我甚至不确定在这里要问什么问题 - 希望我的代码有明显的错误,有人可以指出我正确的方向。我花了一些时间阅读函数的源代码,我我理解它,但我不确定第二个错误的CSRF令牌来自哪里(我以为它会是在会话变量中设置,因此不会改变)。已经过了几个小时,我所有想出来的尝试都失败了。

1 个答案:

答案 0 :(得分:1)

嗯,这是最耗时的错误之一,是我曾经处理过的最平凡的答案之一。

前段时间我在sslOnlySessions添加了makeSessionBackend并忘了它。在尝试用一切可能的方式包裹我的大脑后,我可能做错了什么,我退后一步,试图想出一个不同的角度来解决问题,它就像一堆砖头一样打击我。

我发布了这个答案,因为10年后的某个人将会犯同样的愚蠢错误,在搜索错误的代码后,最终启动Google并找到一个简单的答案。

Godspeed,未来的Haskeller。