【发布时间】:2018-07-28 12:24:30
【问题描述】:
我目前正在为一个课程项目使用 Yesod 框架开发一个 Web 服务器。我是 Haskell 的新手,我着迷于它与我所知道的有关编程语言的所有其他事物的不同之处。然而,并不是所有的玫瑰。有时我会卡住几天,这个问题就是关于这样一个案例的。
这些是验证请求附带的不记名令牌的函数:
isDateExpired :: Maybe JWT.NumericDate -> Maybe JWT.NumericDate -> IO (Maybe Bool)
isDateExpired exptime currtime = return $ (<) <$> exptime <*> currtime
validateToken :: Handler AuthResult
validateToken = do
bearerToken <- lookupBearerAuth
master <- getYesod
when (isNothing bearerToken) $ permissionDenied "Token not present in headers."
let decodedAndVerified = join $ JWT.decodeAndVerifySignature (JWT.secret (clientSecret master)) <$> bearerToken
claimset = JWT.claims <$> decodedAndVerified
audience = join $ JWT.aud <$> claimset
iss = join $ JWT.iss <$> claimset
expiration = join $ JWT.exp <$> claimset
case audience of
Just a -> do
case a of
Left uniqueAud -> do
when (Just uniqueAud /= JWT.stringOrURI (clientId master)) $ permissionDenied "Invalid aud."
Right _ -> permissionDenied "Tokens with multiple aud values not currently supported."
_ -> permissionDenied "Audience not defined."
when (iss /= JWT.stringOrURI (configIssuer master)) $
permissionDenied "Invalid issuer."
when (isNothing claimset) $
permissionDenied "Claimset invalid."
let mExpired = JWT.numericDate <$> getPOSIXTime >>= isDateExpired expiration
--FIXME Currently, this next part has to be at the end of the function.
liftIO $ mExpired >>=
\y -> if isNothing y then return $ Unauthorized "Expiration date missing."
else if y==Just True then return $ Unauthorized "Invalid expiration date."
else return $ Authorized
好吧,这段代码确实有效。它正确地验证了令牌。但是,正如您在 FIXME 中看到的那样,validateToken 函数的最后一部分非常hacky。它必须是最后一行,这让我很恼火。
根据我收集到的信息,处理此问题的正确方法是使用when,就像在上面的案例中所做的那样。问题是,我希望这里有人可以阐明,在验证到期日期时,我最终在 mExpired 变量中得到了一个 IO (Maybe Bool)。而when 不接受。
我想做的是(在伪 Haskell 中)这样的事情:
when (isNothing mExpired || mExpired == Just True) $ permissionDenied "Invalid expiration date."
然后我可以在此之后检查其他内容,并在函数的末尾输入Authorized,一切都正确且美观。
这样的事情可能吗?
仅供参考:permissionDenied 的类型是 Failure ErrorResponse m => String -> m a
【问题讨论】:
-
旁注:在您的用例中,
currtimeinisDateExpired是Nothing意味着在JWT.numericDate中存在解析失败,您最终会将此案例与到期日期合并-失踪失败。在这种情况下,这并不重要(据我所知,getPOSIXTime不能为此目的产生无效的日期),但最好注意这种情况,在这种情况下,某些事情可能会溜走裂缝。