Haskell的持久性主题返回500 Internal Server Error

时间:2018-11-03 04:54:45

标签: haskell haskell-persistent

以下代码在localhost:3000处启动Web服务器。

#!/usr/bin/env stack
-- stack script --resolver=lts-12.16

{-# LANGUAGE EmptyDataDecls             #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE GADTs                      #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE ViewPatterns               #-}
import Yesod
import Database.Persist.Sqlite
import Control.Monad.Trans.Resource (runResourceT)
import Control.Monad.Logger (runStderrLoggingT)
import Data.Text

-- Define our entities as usual
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Book
    title Text
    author Text
    publisher Text
    date Text
    price Int
    deriving Show
|]

-- We keep our connection pool in the foundation. At program initialization, we
-- create our initial pool, and each time we need to perform an action we check
-- out a single connection from the pool.
data SQLi = SQLi ConnectionPool

-- We'll create a single route, to access a person. It's a very common
-- occurrence to use an Id type in routes.
mkYesod "SQLi" [parseRoutes|
/ HomeR GET
/book/#BookId BookR GET
|]

-- Nothing special here
instance Yesod SQLi

-- Now we need to define a YesodPersist instance, which will keep track of
-- which backend we're using and how to run an action.
instance YesodPersist SQLi where
    type YesodPersistBackend SQLi = SqlBackend

    runDB action = do
        SQLi pool <- getYesod
        runSqlPool action pool

searchFrame :: [Entity Book] -> Widget
searchFrame books = 
  [whamlet|
    <table border=1>
      <tr>
        <th>ID
        <th>Title
        <th>Author
        <th>Publisher
        <th>Publication date
        <th>Price
      $forall Entity bookid book <- books
        <tr>
          <td>
            <a href=@{BookR bookid}>#{show bookid}
          <td>
            #{bookTitle book}
          <td>
            #{bookAuthor book}
          <td>
            #{bookPublisher book}
          <td>
            #{bookDate book}
          <td>
            #{bookPrice book}
  |]

-- List all people in the database
getHomeR :: Handler Html
getHomeR = do
  mBookAuthor <- lookupGetParam "author"
  maybe (do
    books <- runDB $ selectList [] [Asc BookId]
    defaultLayout $ searchFrame books)
    (¥author -> do
       books <- runDB $ selectList [BookAuthor ==. author] [Asc BookId]

       defaultLayout $ [whamlet|
         <h1>Search books manually
         ^{searchFrame books}
       |]) $ mBookAuthor

-- We'll just return the show value of a person, or a 404 if the Person doesn't
-- exist.
getBookR :: BookId -> Handler String
getBookR bookId = do
    book <- runDB $ get404 bookId
    return $ show book

openConnectionCount :: Int
openConnectionCount = 10

main :: IO ()
main = runStderrLoggingT $ withSqlitePool ":memory:" openConnectionCount $ ¥pool -> liftIO $ do
    runResourceT $ flip runSqlPool pool $ do
        runMigration migrateAll
        insert $ Book "A Midsummer Night's Dream" "Shakespeare" "A bookstore"   "1979/01" 600
        insert $ Book "Hamlet"    "Shakespeare" "B bookstore"   "1997/04" 1260
        insert $ Book "Macbeth"   "Shakespeare" "C bookstore"   "2001/05" 1530
        insert $ Book "King Lear"     "Shakespeare" "D bookstore" "2004/07" 1890
    warp 3000 $ SQLi pool

然后,加载http://localhost:3000/?author=' AND EXTRACTVALUE(0, (SELECT CONCAT('$', id, ':', pwd) FROM users LIMIT 0, 1)) #有时会导致500 Internal Server Error,即使我们加载诸如http://localhost:3000/这样的普通页面,也会发出此错误消息

实际上,这可能是SQL注入的攻击媒介。因此,我对这是由袭击或其他原因造成的天气感到困惑。有人可以解释这种行为吗?

1 个答案:

答案 0 :(得分:0)

糟糕。我错过了withSqlitePool should not be used with :memory:。通过给它一个文件名,该问题得以解决。