7

私は優れたCFWeb開発者になり<cfqueryparam>、SQLクエリに到達するすべてのFORMまたはURL要素を使用しようとしています。

この場合、ユーザーがORDERBY句を動的に制御できるようにしようとしています。

<cfquery datasource="MyDSN" name="qIncidents">
  SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
  FROM Incidents
  WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
  ORDER BY <cfqueryparam cfsqltype="cf_sql_varchar" value="#SortBy#">
</cfquery>

これを行うと、次のエラーが発生します。

ORDER BY番号1で識別されるSELECT項目には、列位置を識別する式の一部として変数が含まれています。変数は、列名を参照する式で並べ替える場合にのみ許可されます。

これを安全に行う方法について何か提案はありますか?

4

5 に答える 5

13

残念ながら、OrderBy句でCFQUERYPARAMを直接使用することはできません。

Order Byを動的に使用したいが、それでも安全に使用したい場合は、CFSWITCHまたは同様の構造を設定して、条件(URL変数など)に応じてSortBy変数を変更できます。いつものように、ユーザーから直接値を渡すのではなく、ユーザーの入力を見て、それに基づいて可能な値の所定のリストから選択するだけです。次に、標準の構文を使用します。

ORDER BY #SortBy#
于 2009-05-20T17:46:19.650 に答える
4

アーロンの答えを拡張します。私が行うことの 1 つは、listfindnocase() を使用して、order by 句に渡される引数が有効であることを確認することです。

<cfset variables.safeSortColumn = "name">
<cfset variables.safeSortOrder = "desc">

<cfparam name="url.sortcolumn" type="string" default="#variables.safeSortColumn#">
<cfparam name="url.sortorder" type="string" default="#variables.safeSortOrder#">

<cfif listfindnocase("name,age,address", url.sortcolumn)>
    <cfset variables.safeSortColumn = url.sortcolumn>
</cfif>

<cfif listfindnocase("desc,asc", url.sortorder)>
    <cfset variables.safeSortOrder = url.sortorder>
</cfif>

<cfquery>
select *
from mytable
order by #variables.safeSortcolumn# #variables.safeSortorder#
</cfquery>
于 2009-05-21T12:57:48.527 に答える
2

列参照に序数値を使用する際の問題は、(私が信じている) create table SQL ステートメントが実行された時点での序数値であることです。列が実際の序数値を表していない可能性があります。これには cfqueryparam を使用しないでください。

リクエスト変数(url、フォーム)で数字を使用してソートする列を指定し、それをスイッチで使用して実際の列名に変換するというアイデアが好きです-したがって、列名をユーザー。

いつ/なぜ cfqueryparam を使用するかについては、入力の検証と SQL インジェクションの防止だけではないことに注意してください (これは非常に素晴らしいボーナスですが) - cfqueryparam を使用すると、データベースへの基になる SQL が、SQL バインドを使用してドライバーを介して送り返されます。変数 - プレースホルダー値。データベース オプティマイザーは、より一般的な形式で使用するインデックスを決定できます。したがって、次のような SQL ステートメントを送信すると: SELECT * FROM product WHERE ID=1 and SELECT * FROM product WHERE ID=2オプティマイザは両方の回で実行されます。ただし、バインド変数を使用すると、SQL は SELECT * FROM product WHERE ID=? のようになります。(?=1) と SELECT * FROM product WHERE ID=? (?=2) であるため、オプティマイザーは最初の分析のキャッシュされた結果を使用して、2 番目のクエリで使用するインデックスを正確に知ることができます。SQL とデータベースの複雑さにもよりますが、これは時間の大幅な節約になる可能性があります。私の経験では、where 句にオラクルと日付/時刻の列を使用すると、非常に役立つパフォーマンスが得られます。

cfqueryparamを使用する場所に関しては、SQLバインド変数を使用できる場所...

ジョン

于 2009-05-21T18:18:40.610 に答える
0

私はこの問題でより少ないコードを投げると思った:

<cfset sortColumns = {IncidentID = "IncidentID", AnimalID = "AnimalID", IntakeDate = "IntakeDate", DxDate = "DxDate", OutcomeDate = "OutcomeDate"}>
<cfset sortDirections = {ASC = "ASC", DESC = "DESC"}>

<cfquery datasource="MyDSN" name="qIncidents">
    SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
    FROM Incidents
    WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
    ORDER BY #sortColumns[sortBy]# #sortDirections[sortDirection]#
</cfquery>

sortByとsortDirectionがURLを介して、またはどこからでも入ってくる場所。

これはクリーンで、ORDERBY句を介して何も注入できないので気に入っています。

コメントはありますか?

于 2009-06-24T22:02:10.067 に答える
0

「注文句で cfqueryparam を使用すると MySQL で問題ありません」というコメントについて。はい、MySQL データソースでは許可されていると思います。列の序数を使用していますが、列名ではありません(代わりに定数文字列として扱われているようです)。

残念ながら、MS SQL データソースではまったく機能しないようです。少なくとも私が言えることからではありません。

<!--- this works --->
<cfset url.sortColumnNumber = "3">
<cfquery name="getDataByPosition" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM TestTable
   ORDER BY <cfqueryparam value="#url.sortColumnNumber#" cfsqltype="cf_sql_integer"> ASC
</cfquery>
<cfdump var="#getDataByPosition#">

<!--- this does NOT work --->
<cfset url.sortColumnName = "DateAdded">
<cfquery name="getDataByName" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM    TestTable
   ORDER BY <cfqueryparam value="DateAdded" cfsqltype="cf_sql_varchar"> ASC
</cfquery>
<cfdump var="#getDataByName#">

更新:序数に関するコメントについて:いいえ、基になるテーブルではなく、選択リストの列の位置を参照していると思います。それでいいはずです。

はい、SQL インジェクション保護が cfqueryparam の主な目的ではないことに同意します。したがって、バインド変数の説明は適切な追加でした。

于 2009-05-21T16:46:07.240 に答える