如何将基本身份验证添加到Scotty中间件? [英] How to add basic auth to Scotty middleware?
问题描述
我目前正在制作Scotty API,但找不到任何basicAuth实现的示例(Wai Middleware HttpAuth).
I'm currently making a Scotty API and I couldn't find any examples of basicAuth implementations (Wai Middleware HttpAuth).
具体来说,我想向一些端点(即以"admin"开头的端点)添加基本身份验证标头(用户,密码).我已经完成了所有设置,但似乎无法区分哪些端点需要auth,哪些端点不需要auth.我知道我需要使用,但是它使用Yesod,因此我无法将其翻译为Scotty.
Specifically, I want to add basic auth headers (user, pass) to SOME of my endpoints (namely, ones that start with "admin"). I have everything set up, but I can't seem to make the differentiation as to which endpoints require auth and which ones don't. I know I need to use something like this, but it uses Yesod, and I wasn't able to translate it to Scotty.
到目前为止,我有这个:
So far, I have this:
routes :: (App r m) => ScottyT LText m ()
routes = do
-- middlewares
middleware $ cors $ const $ Just simpleCorsResourcePolicy
{ corsRequestHeaders = ["Authorization", "Content-Type"]
, corsMethods = "PUT":"DELETE":simpleMethods
}
middleware $ basicAuth
(\u p -> return $ u == "username" && p == "password")
"My Realm"
-- errors
defaultHandler $ \str -> do
status status500
json str
-- feature routes
ItemController.routes
ItemController.adminRoutes
-- health
get "/api/health" $
json True
但是它将身份验证添加到我的所有请求中.我只在其中一些中需要它.
But it adds authentication to all my requests. I only need it in some of them.
非常感谢您!
推荐答案
您可以使用 AuthSettings
的 authIsProtected
字段来定义函数 Request->;IO Bool
,用于确定特定(Wai) Request
是否受基本身份验证的授权.特别是,您可以检查URL路径组件并以此方式确定.
You can use the authIsProtected
field of the AuthSettings
to define a function Request -> IO Bool
that determines if a particular (Wai) Request
is subject to authorization by basic authentication. In particular, you can inspect the URL path components and make a determination that way.
不幸的是,这意味着授权检查与Scotty路由完全分开.在您的情况下,此方法效果很好,但可能难以通过Scotty路由进行细粒度的授权控制.
Unfortunately, this means that the check for authorization is completely separated from the Scotty routing. This works fine in your case but can make fine-grained control of authorization by Scotty route difficult.
无论如何, AuthSettings
是您的源中重载的"My Realm"
字符串,根据文档,建议使用定义设置的方式重载的字符串编写如下内容:
Anyway, the AuthSettings
are the overloaded "My Realm"
string in your source, and according to the documentation, the recommended way of defining the settings is to use the overloaded string to write something like:
authSettings :: AuthSettings
authSettings = "My Realm" { authIsProtected = needsAuth }
这看起来很可怕,但是无论如何, needsAuth
函数将具有签名:
That looks pretty horrible, but anyway, the needsAuth
function will have signature:
needsAuth :: Request -> IO Bool
因此它可以检查Wai Request
并在IO中做出有关页面是否首先需要基本身份验证的决定.在 Request
上调用 pathInfo
会为您提供路径组件的列表(没有主机名和查询参数).因此,对于您的需求,以下应该起作用:
so it can inspect the Wai Request
and render a decision in IO on whether or not the page needs basic authentication first. Calling pathInfo
on the Request
gives you a list of path components (no hostname and no query parameters). So, for your needs, the following should work:
needsAuth req = return $ case pathInfo req of
"admin":_ -> True -- all admin pages need authentication
_ -> False -- everything else is public
请注意,这些是已解析的非查询路径组件,因此,/admin
和/admin/
和/admin/whatever
甚至是/admin/?q = hello
受保护,但显然/administrator/...
不受保护.
Note that these are the parsed non-query path components, so /admin
and /admin/
and /admin/whatever
and even /admin/?q=hello
are protected, but obviously /administrator/...
is not.
完整示例:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Network.Wai.Middleware.HttpAuth
import Data.Text () -- needed for "admin" overloaded string in case
import Network.Wai (Request, pathInfo)
authSettings :: AuthSettings
authSettings = "My Realm" { authIsProtected = needsAuth }
needsAuth :: Request -> IO Bool
needsAuth req = return $ case pathInfo req of
"admin":_ -> True -- all admin pages need authentication
_ -> False -- everything else is public
main = scotty 3000 $ do
middleware $ basicAuth (\u p -> return $ u == "username" && p == "password") authSettings
get "/admin/deletedb" $ do
html "<h1>Password database erased!</h1>"
get "/" $ do
html "<h1>Homepage</h1><p>Please don't <a href=/admin/deletedb>Delete the passwords</a>"
这篇关于如何将基本身份验证添加到Scotty中间件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!