3

「コンピュータ」サンプルのようなリストページを作成しようとしています。私の環境はPlay2.0とPostrgreSQL9.0です

Userオブジェクトに次のメソッドがあります。

 def list(page: Int = 0, pageSize: Int = 10, orderBy: Int = 1, filter: String = "%"): Page[User] = {
    val offset = pageSize * page
    val mode = if (orderBy > 0) "ASC NULLS FIRST" else "DESC NULLS LAST"

    Logger.debug("Users.list with params: page[%d] pageSize[%d] orderBy[%d] filter[%s] order[%s]".format(page, pageSize, orderBy, filter, mode))

    DB.withConnection {
      implicit connection =>

        val users = SQL(
          """
            select * from publisher
            where name ilike {filter}
            order by {orderBy} %s
            limit {pageSize} offset {offset}
          """.format(mode)
        ).on(
          'pageSize -> pageSize,
          'offset -> offset,
          'filter -> filter,
          'orderBy -> scala.math.abs(orderBy)
        ).as(User.simple *)

        val totalRows = SQL(
          """
            select count(*) from publisher
            where name like {filter}
          """
        ).on(
          'filter -> filter
        ).as(scalar[Long].single)

        Page(users, page, offset, totalRows)
    }

  }

'orderBy'のどの値を指定するかは関係ありません。順序は、常にエンティティのIDに基づいています。

Anormによって生成されたクエリは有効なPostgreSQLであり、データベースに対して直接実行すると正常に機能します。しかし、Anormパーサーが結果が返される順序を無視し、代わりに「id」で順序付けられたリストを返す場合のようです。

クエリを単純化しようとしました"select * from publisher order by 2 ASC/DESC"が、何も修正されていません。順序は、戻り時にAnormによって無視されます。

この問題を解決する方法について何か提案はありますか?

4

1 に答える 1

4

Play のメーリング リストの Guillaume のおかげで、私は回避策を見つけました。

order by 以外のすべてのプレースホルダーが機能します。さらに悪い点は、ログをたどると、ドライバーが正しいクエリを生成し、PostgreSQL がそれを受信して​​いることです。何がどうなっているのかわかりませんが、非常に紛らわしいですが、そのプレースホルダーを削除すると、うまくいきます。

憂鬱 :(

私はこのようにそれを解決しました:

val users = SQL(
  """
    select * from publisher
    where name ilike {filter}
    order by %d %s
    limit {pageSize} offset {offset}
  """.format(scala.math.abs(orderBy), mode)
).on(
  'pageSize -> pageSize,
  'offset -> offset,
  'filter -> filter
).as(User.simple *)

これで、「SQL INJECTION」と叫ぶことになります。リラックス。どういうわけか可能かもしれませんが、orderByは整数です (安全性を高めるために abs 値に変換します)。文字列を提供するコントローラーを呼び出そうとするとorderBy、Play はエラーを返し404ます。したがって、整数のみが許可されます。指定された整数に対応する列がない場合、order byは無視されます。したがって、理想的ではありませんが、それほど悪くはありません。

于 2012-03-20T21:23:05.450 に答える