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.
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.
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 }
That looks pretty horrible, but anyway, the needsAuth
function will have signature:
needsAuth :: Request -> IO Bool
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
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.
A full example:
{-# 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>"
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…