簡體   English   中英

Snap:使用CSRF檢查程序包裝auth處理程序

[英]Snap: wrapping auth handler with CSRF checker

我有以下處理程序,我用它來檢查給定處理程序的授權:

  needsAuth :: Handler App (AuthManager App) () -> Handler App App ()
  needsAuth x = with auth $ requireUser auth noUserHandler x
    where noUserHandler = handleLogin (Just "must be logged in")

Site.h我指定了這樣的路由:( ("/transfers", needsAuth handleTransfers)其中("/transfers", needsAuth handleTransfers)的簽名是handleTransfers :: Handler App (AuthManager App) ()

我的應用程序中只有少數處理程序具有用戶提交的表單; 我想對它們使用CSRF檢查,雖然使用CSRF檢查處理程序包裝授權處理程序會很方便,所以我可以將路由更改為:

("/test", handleCSRF $ needsAuth handleTest)

根據snap-extras包中的想法,我創建了函數handleCSRF:

handleCSRF :: Handler b v () -> Handler b v ()
handleCSRF x = do
  m <- getsRequest rqMethod
  if m /= POST
    then x
    else do tok <- getParam "_csrf"
          s <- gets session
          realTok <- withSession s csrfToken
          if tok == Just (E.encodeUtf8 realTok)
            then x
            else writeText $ "CSRF error"

編譯錯誤是:

Couldn't match type `SessionManager' with `AuthManager b'
When using functional dependencies to combine
  MonadState v (Handler b v),
    arising from the dependency `m -> s'
    in the instance declaration in `snap-0.13.2.5:Snap.Snaplet.Internal.Type s'
  MonadState (AuthManager b) (Handler b SessionManager),
    arising from a use of `gets' at src\Site.hs:106:20-23
In a stmt of a 'do' block: s <- gets session
In the expression:
  do { tok <- getParam "_csrf";
       s <- gets session;
       realTok <- withSession s csrfToken;
       if tok == Just (E.encodeUtf8 realTok) then
           x
       else
           writeText $ "CSRF error" }

我已經嘗試了許多不同的變體,但得到了不同品種的編譯錯誤......我正朝着正確的方向前進嗎? 這是Snap中的正確方法嗎?

編輯 :這是一些額外的信息:

data App = App
{ _heist :: Snaplet (Heist App)
, _sess  :: Snaplet SessionManager
, _auth  :: Snaplet (AuthManager App)
, _wmConfig  :: WMConfig
}
makeLenses ''App

我正在初始化會話snaplet,如下所示:

   s <- nestSnaplet "sess" sess $
       initCookieSessionManager "site_key.txt" "sess" (Just 1200)

編輯#2 /解決方案 ... @mightybyte通過IRC給了我解決方案,用realTok <- withSession sess (with sess csrfToken)取代了realTok系列,該工作正常。

尼爾,提前謝謝

嘗試這個:

handleCSRF :: Handler App App () -> Handler App App ()
handleCSRF x = do
  m <- getsRequest rqMethod
  if m /= POST
    then x
    else do tok <- getParam "_csrf"
          realTok <- withSession sess csrfToken
          if tok == Just (E.encodeUtf8 realTok)
            then x
            else writeText $ "CSRF error"

withSession的第一個參數應該是鏡頭,而不是SessionManager本身。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM