我正在使用基于Haskell Snap的Web应用程序,我希望公开一个将由远程服务调用的API端点,而无需事先建立经过身份验证的会话;但是,我确实希望对该请求进行身份验证,因此应在请求时提供凭据。
您可以想象包含四个字段的请求:
有效负载ID和文件可能与此问题无关,但我包含它们是因为我(a)需要支持此请求中的文件上传(据我所知,它限制用于发送字段的编码)和( b)需要检索至少一个非文件字段。
,当我在没有认证的情况下进行设置时,这些事情的组合会带来一些困难按照Snap的说法,让我们调用此处理程序uploadHandler
。
如上所述,我在没有身份验证的情况下工作正常,设置如下:
uploadHandler :: Handler App App ()
uploadHandler = do
-- collect files / form fields and process as needed.
-- and using the routes:
routes :: [(ByteString, Handler App App ())]
routes = [ ("/login", with auth handleLoginSubmit)
, ("/logout", with auth handleLogout)
, ("/new_user", with auth handleNewUser)
-- handle the upload:
, ("/upload", handleUpload)
]
天真的解决方案是简单地添加' auth'并更改handleUpload
的类型:
uploadHandler :: Handler App (AuthManager App) ()
uploadHandler = do
-- collect files / form fields and process as needed.
-- and using the routes:
routes :: [(ByteString, Handler App App ())]
routes = [ ("/login", with auth handleLoginSubmit)
, ("/logout", with auth handleLogout)
, ("/new_user", with auth handleNewUser)
-- handle the upload, with auth:
, ("/upload", with auth handleUpload)
]
但是,这似乎需要两个请求:(i)验证并建立会话,(ii)发送包含实际有效载荷的POST请求。
我找到了一种在一个请求中执行此操作的方法,但似乎应该有更优雅的方法。这是我一起被黑客攻击的示例限制POST处理程序:
restrictedPOST :: Handler App (AuthManager App) ()
restrictedPOST = do
mName <- getPostParam "username"
mPass <- getPostParam "password"
let uName = C8.unpack $ fromMaybe "" mName
pass = ClearText $ fromMaybe "" mPass
authResult <- loginByUsername (T.pack uName) pass False
case authResult of
Left authFail -> writeText "Could not log in"
Right user -> writeText (T.append "Hello " (userLogin user))
是否有类似&#39;与auth&#39;我可以使用而不是将此示例(restrictedPOST
)转换为组合器?我意识到它可能需要知道哪些字段可以获取凭证,但我对网络服务知之甚少(也许还有其他方法?也许这完全没有问题,我只是不知道如何检查auth是否有POST请求。我可以接受任何建议!)
答案 0 :(得分:1)
我不认为您了解with auth
正在做什么。它与是否需要身份验证无关。它所做的就是将Handler b (AuthManager b)
转换为Handler b v
。没有执行权限检查。你的restrictedPOST函数有正确的想法。