Support for HttpOnly and Secure attributes on the core.

This commit is contained in:
Felipe Lessa 2015-05-25 19:57:43 -03:00
parent c2afd3e1a5
commit e5203db715
4 changed files with 43 additions and 5 deletions

View File

@ -12,6 +12,8 @@ module Web.ServerSession.Frontend.Yesod
, setIdleTimeout , setIdleTimeout
, setAbsoluteTimeout , setAbsoluteTimeout
, setPersistentCookies , setPersistentCookies
, setHttpOnlyCookies
, setSecureCookies
, State , State
) where ) where

View File

@ -14,7 +14,7 @@ import Data.ByteString (ByteString)
import Data.Default (def) import Data.Default (def)
import Web.PathPieces (toPathPiece) import Web.PathPieces (toPathPiece)
import Web.ServerSession.Core import Web.ServerSession.Core
import Web.ServerSession.Core.Internal (cookieName) import Web.ServerSession.Core.Internal (cookieName, httpOnlyCookies, secureCookies)
import Yesod.Core (MonadHandler) import Yesod.Core (MonadHandler)
import Yesod.Core.Handler (setSessionBS) import Yesod.Core.Handler (setSessionBS)
import Yesod.Core.Types (Header(AddCookie), SessionBackend(..)) import Yesod.Core.Types (Header(AddCookie), SessionBackend(..))
@ -43,13 +43,15 @@ import qualified Web.Cookie as C
-- ... -- ...
-- @ -- @
-- --
-- For example, if you wanted to disable the idle timeout and decrease the -- For example, if you wanted to disable the idle timeout,
-- absolute timeout to one day, you could change that line to: -- decrease the absolute timeout to one day and mark cookies as
-- \"Secure\", you could change that line to:
-- --
-- @ -- @
-- makeSessionBackend = simpleBackend opts . SqlStorage . appConnPool -- makeSessionBackend = simpleBackend opts . SqlStorage . appConnPool
-- where opts = setIdleTimeout Nothing -- where opts = setIdleTimeout Nothing
-- . setAbsoluteTimeout (Just $ 60*60*24) -- . setAbsoluteTimeout (Just $ 60*60*24)
-- . setSecureCookies True
-- @ -- @
simpleBackend simpleBackend
:: (MonadIO m, Storage s) :: (MonadIO m, Storage s)
@ -92,7 +94,8 @@ createCookie state cookieNameBS session =
, C.setCookiePath = Just "/" , C.setCookiePath = Just "/"
, C.setCookieExpires = cookieExpires state session , C.setCookieExpires = cookieExpires state session
, C.setCookieDomain = Nothing , C.setCookieDomain = Nothing
, C.setCookieHttpOnly = True , C.setCookieHttpOnly = httpOnlyCookies state
, C.setCookieSecure = secureCookies state
} }

View File

@ -20,6 +20,8 @@ module Web.ServerSession.Core
, setIdleTimeout , setIdleTimeout
, setAbsoluteTimeout , setAbsoluteTimeout
, setPersistentCookies , setPersistentCookies
, setHttpOnlyCookies
, setSecureCookies
, ForceInvalidate(..) , ForceInvalidate(..)
) where ) where

View File

@ -16,6 +16,8 @@ module Web.ServerSession.Core.Internal
, setIdleTimeout , setIdleTimeout
, setAbsoluteTimeout , setAbsoluteTimeout
, setPersistentCookies , setPersistentCookies
, setHttpOnlyCookies
, setSecureCookies
, loadSession , loadSession
, checkExpired , checkExpired
, nextExpires , nextExpires
@ -171,7 +173,9 @@ class MonadIO (TransactionM s) => Storage s where
-- --
-- * Idle and absolute timeouts ('setIdleTimeout' and 'setAbsoluteTimeout'). -- * Idle and absolute timeouts ('setIdleTimeout' and 'setAbsoluteTimeout').
-- --
-- * Whether cookies should be persistent ('setPersistentCookies') -- * Whether cookies should be persistent
-- ('setPersistentCookies'), HTTP-only ('setHTTPOnlyCookies')
-- and/or secure ('setSecureCookies').
-- --
-- Create a new 'State' using 'createState'. -- Create a new 'State' using 'createState'.
data State s = data State s =
@ -183,6 +187,8 @@ data State s =
, idleTimeout :: !(Maybe NominalDiffTime) , idleTimeout :: !(Maybe NominalDiffTime)
, absoluteTimeout :: !(Maybe NominalDiffTime) , absoluteTimeout :: !(Maybe NominalDiffTime)
, persistentCookies :: !Bool , persistentCookies :: !Bool
, httpOnlyCookies :: !Bool
, secureCookies :: !Bool
} deriving (Typeable) } deriving (Typeable)
@ -199,6 +205,8 @@ createState sto = do
, idleTimeout = Just $ 60*60*24*7 -- 7 days , idleTimeout = Just $ 60*60*24*7 -- 7 days
, absoluteTimeout = Just $ 60*60*24*60 -- 60 days , absoluteTimeout = Just $ 60*60*24*60 -- 60 days
, persistentCookies = True , persistentCookies = True
, httpOnlyCookies = True
, secureCookies = False
} }
@ -269,6 +277,29 @@ setPersistentCookies :: Bool -> State s -> State s
setPersistentCookies val state = state { persistentCookies = val } setPersistentCookies val state = state { persistentCookies = val }
-- | Set whether cookies should be HTTP-only (@True@) or not
-- (@False@). Cookies marked as HTTP-only (\"HttpOnly\") are not
-- accessible from client-side scripting languages such as
-- JavaScript, thus preventing a large class of XSS attacks.
-- It's highly recommended to set this attribute to @True@.
--
-- Defaults to @True@.
setHttpOnlyCookies :: Bool -> State s -> State s
setHttpOnlyCookies val state = state { httpOnlyCookies = val }
-- | Set whether cookies should be mared \"Secure\" (@True@) or not
-- (@False@). Cookies marked as \"Secure\" are not sent via
-- plain HTTP connections, only via HTTPS connections. It's
-- highly recommended to set this attribute to @True@. However,
-- since many sites do not operate over HTTPS, the default is
-- @False@.
--
-- Defaults to @False@.
setSecureCookies :: Bool -> State s -> State s
setSecureCookies val state = state { secureCookies = val }
-- | Load the session map from the storage backend. The value of -- | Load the session map from the storage backend. The value of
-- the session cookie should be given as argument if present. -- the session cookie should be given as argument if present.
-- --