2

私がうまくいかないという本当に奇妙なことを手に入れました。

CFC (guest.cfc) 内に 3 つのメソッドがあります。

- save
- create
- update

引数コレクションを save メソッドに渡します。

saveGuest = objGuest.save(argumentcollection=guestStruct)

Identier が含まれている場合は、argumentCollecion を update メソッドに渡します。含まれていない場合は、コレクションを create メソッドに渡します。

これは、アプリ内のある場所から呼び出すと正常に動作しますが、save メソッドへの新しい呼び出しを作成すると、create メソッドは正常に動作しますが、update メソッドで ID が渡されると、UPDATE というエラーが表示されます。変数が存在しません。

しかし、cfc のオブジェクトを作成して呼び出し方を変えると、うまくいきます。

それで..

saveObject =  update(argumentCollection = arguments;

動作しません。更新変数が存在しないというエラーを受け取ります。

saveObject =  createObject("component",'guest').update(argumentCollection = arguments);

動作します。

これらの呼び出しは両方とも、guest.cfc 自体の中で発生していることに注意してください。

この問題は、フォーム構造体を save メソッドに渡した場合には発生しませんが、(XML インポートから構築された) 標準構造体を渡した場合には発生します。

非常に奇妙な。

誰がこれを引き起こしているのかについて何か考えがありますか?


4月24日編集 - guest.cfcのコードを追加


<cffunction name="save" output="false" access="remote" hint="save guest">
    <cfargument name="title" type="any" required="false" default="" />
    <cfargument name="first_name" type="any" required="false" default="" />
    <cfargument name="surname" type="any" required="false" default="" />
    <cfargument name="dob" type="any" required="false" default="NULL" />
    <cfargument name="partner_first_name" type="any" required="false" default="" />
    <cfargument name="partner_surname" type="any" required="false" default="" />
    <cfargument name="partner_dob" type="any" required="false" default="NULL" />
    <cfargument name="address_1" type="any" required="false" default="" />
    <cfargument name="address_2" type="any" required="false" default="" />
    <cfargument name="address_3" type="any" required="false" default="" />
    <cfargument name="city" type="any" required="false" default="" />
    <cfargument name="state" type="any" required="false" default="" />
    <cfargument name="postcode" type="any" required="false" default="" />
    <cfargument name="country" type="any" required="false" default="" />
    <cfargument name="phone_bh" type="any" required="false" default="" />
    <cfargument name="phone_ah" type="any" required="false" default="" />
    <cfargument name="phone_mob" type="any" required="false" default="" />
    <cfargument name="fax" type="any" required="false" default="" />
    <cfargument name="email" type="any" required="false" default="" />
    <cfargument name="business" type="any" required="false" default="" />
    <cfargument name="notes" type="any" required="false" default="" />
    <cfargument name="referer" type="any" required="false" default="" />
    <cfargument name="prospect" type="any" required="false" default="" />
    <cfargument name="occasion" type="any" required="false" default="" />
    <cfargument name="occasion_date" type="any" required="false" default="NULL" />


    <!---pass to Create or Save--->
    <cfif NOT isdefined("arguments.guest_id") OR arguments.guest_id EQ "0">
        <cfset saveObject =  create(argumentCollection = arguments) />
    <cfelse>
        <cfset saveObject =  update(argumentCollection = arguments) />
    </cfif>

    <cfreturn saveObject>

</cffunction>


<!---CREATE--->
<cffunction name="create" output="false" access="private" returntype="struct" hint="Create a New Item">
    <cfargument name="provider_id" type="any" required="false" default="#session.providerID#" />
    <cfargument name="ext_ref_id" type="any" required="false" default="NULL" />
    <cfargument name="tstamp" type="any" required="false" default="#session.tStamp#" />

    <cfif isValid('date',arguments.occasion_date)>
        <cfset iOccasionDate = createODBCDateTime(arguments.occasion_date)>
    <cfelse>
        <cfset iOccasionDate = "NULL">
    </cfif>

    <cfset returnStruct = StructNew()>

    <cfquery name="insertGuest" datasource="#Application.ds#">
        INSERT INTO guest (provider_id, ext_ref_id, title, first_name, surname, full_name, partner_first_name, partner_surname, partner_full_name, address_1, address_2, address_3, city, state, postcode, country, phone_bh, phone_ah, phone_mob, fax, email, company, notes, referer, prospect, occasion, occasion_date, tstamp)
        VALUES (#provider_id#, #ext_ref_id#, '#arguments.title#', '#arguments.first_name#', '#arguments.surname#', '#arguments.first_name# #arguments.surname#', '#arguments.partner_first_name#', '#arguments.partner_surname#', '#arguments.partner_first_name# #arguments.partner_surname#', '#arguments.address_1#', '#arguments.address_2#', '#arguments.address_3#', '#arguments.city#', '#arguments.state#', '#arguments.postcode#', '#arguments.country#', '#arguments.phone_bh#', '#arguments.phone_ah#', '#arguments.phone_mob#', '#arguments.fax#', '#arguments.email#', '#arguments.company#', '#arguments.notes#', '#arguments.referer#', '#arguments.prospect#', '#arguments.occasion#', #iOccasionDate#, #CreateODBCDateTime(tstamp)#)
    </cfquery>

    <cfquery name="guest" datasource="#Application.ds#">
        SELECT max(guest_id) as id
        FROM guest
        WHERE provider_id = #provider_id#
    </cfquery>

    <cfset returnStruct.id = #guest.id#>
    <cfreturn returnStruct>

</cffunction>



<!---UPDATE--->
<cffunction name="update" output="false" access="private" returntype="struct" hint="Update an existing item">

    <!---general details--->
    <cfquery name="update" datasource="#Application.ds#">
        UPDATE guest
        SET provider_id = provider_id

            <cfif isdefined("arguments.title")>
                ,title = '#arguments.title#'
            </cfif>
            <cfif isdefined("arguments.first_name")>
                ,first_name = '#arguments.first_name#'
            </cfif>
            <cfif isdefined("arguments.surname")>
                ,surname = '#arguments.surname#'
            </cfif>
            <cfif isdefined("arguments.full_name")>
                ,full_name = '#arguments.full_name#'
            </cfif>
            <cfif isdefined("arguments.dob")>
                ,dob = #formDate2odbcDate(arguments.dob)#
            </cfif>

            <cfif isdefined("arguments.partner_first_name")>
                ,partner_first_name = '#arguments.partner_first_name#'
            </cfif>
            <cfif isdefined("arguments.partner_surname")>
                ,partner_surname = '#arguments.partner_surname#'
            </cfif>
            <cfif isdefined("arguments.partner_full_name")>
                ,partner_full_name = '#arguments.partner_full_name#'
            </cfif>
            <cfif isdefined("arguments.partner_dob")>
                ,partner_dob = #formDate2odbcDate(arguments.partner_dob)#
            </cfif>

            <cfif isdefined("arguments.address_1")>
                ,address_1 = '#arguments.address_1#'
            </cfif>
            <cfif isdefined("arguments.address_2")>
                ,address_2 = '#arguments.address_2#'
            </cfif>
            <cfif isdefined("arguments.address_3")>
                ,address_3 = '#arguments.address_3#'
            </cfif>
            <cfif isdefined("arguments.city")>
                ,city = '#arguments.city#'
            </cfif>
            <cfif isdefined("arguments.state")>
                ,state = '#arguments.state#'
            </cfif>
            <cfif isdefined("arguments.postcode")>
                ,postcode = '#arguments.postcode#'
            </cfif>
            <cfif isdefined("arguments.country")>
                ,country = '#arguments.country#'
            </cfif>
            <cfif isdefined("arguments.phone_bh")>
                ,phone_bh = '#arguments.phone_bh#'
            </cfif>
            <cfif isdefined("arguments.phone_ah")>
                ,phone_ah = '#arguments.phone_ah#'
            </cfif>
            <cfif isdefined("arguments.phone_mob")>
                ,phone_mob = '#arguments.phone_mob#'
            </cfif>
            <cfif isdefined("arguments.fax")>
                ,fax = '#arguments.fax#'
            </cfif>
            <cfif isdefined("arguments.email")>
                ,email = '#arguments.email#'
            </cfif>
            <cfif isdefined("arguments.subscribe_email_broadcast")>
                ,subscribe_email_broadcast = '#arguments.subscribe_email_broadcast#'
            </cfif>
            <cfif isdefined("arguments.company")>
                ,company = '#arguments.company#'
            </cfif>
            <cfif isdefined("arguments.notes")>
                ,notes = '#arguments.notes#'
            </cfif>
            <cfif isdefined("arguments.prospect")>
                ,prospect = '#arguments.prospect#'
            </cfif>
            <cfif isdefined("arguments.occasion")>
                ,occasion = '#arguments.occasion#'
            </cfif>
            <cfif isdefined("arguments.occasion_date")>
                ,occasion_date = #formDate2odbcDate(arguments.occasion_date)#
            </cfif>

        WHERE guest_id = #arguments.guest_id#
    </cfquery>

    <cfset returnStruct = structNew()>
    <cfset returnStruct.id = arguments.guest_id>
    <cfreturn returnStruct>

</cffunction>

4

2 に答える 2

2

CFでは、関数内で次のようなものを記述し、そのCFC/テンプレートのグローバル変数スコープでこれらを作成している場合<cfset iOccasionDate = ... ><cfquery name="insertGuest" ...>

<cfset var iOccasionDate = ... >またはを記述して、関数のローカル変数スコープで作成され、他の変数を上書きし<cfset local.iOccasionDate = ... >ないようにする必要があります。<cfquery name="local.insertGuest" ...>


あなたの特定の問題はあなたがこれを持っているからです:

<cfquery name="update" datasource="#Application.ds#">

したがって、更新クエリで更新関数を上書きしています。


注意すべきいくつかの簡単なこと:

  • ローカルスコープはCF9以降で機能します。CF8以下を使用している場合<cfset var local = StructNew() />は、関数の上部に書き込むことでCF8を模倣する必要があります。

  • RailoまたはOpenBDを使用する場合、常にローカルスコープで作成するようにデフォルトの動作を変更する設定があります(これにより、var / localスコープの必要がなくなります)が、ACFにはこのオプションがありません(まだ?)

  • cfqueryparamを使用してください!-サイモンはすでにこれについて言及していますが、繰り返すのに十分重要です。データは、意図的および偶発的なインジェクション攻撃を防ぐために、使用される場所に基づいて常に処理する必要があります。cfqueryの場合は、cfqueryparamを使用することを意味します。

于 2012-04-24T13:54:05.163 に答える
2

CFC コードと呼び出し元のコードのサンプルがなければ、より正確にするのは少し難しいですが、コンポーネントの init() を確認することをお勧めします。init() メソッドを取得しましたか?それを呼び出していますか? たとえば、コンポーネント定義の概要

<cfcomponent>

    <cffunction name="init" access="public">
        <cfreturn this>
    </cffunction>

    <cffunction name="save" access="public">
        <!--- logic --->
    </cffunction>

    <cffunction name="create" access="public">
        <!--- logic --->
    </cffunction>

    <cffunction name="update" access="public">
        <!--- logic --->
    </cffunction>

</cfcomponent>

これは、次のいずれかによって呼び出されます。

<cfscript>
    // This will work in CF9 upwards
    objCFC = new guest(/* add any arguments you have in the init() method here */);
    objCFC.update(......);

    // This also works
    objCFC = CreateObject('component','guest').init(/* add any arguments you have in the init() method here */);
    objCFC.update(......);
</cfscript>

あなたの例に従って編集

そのCFCは厄介です。さまざまな明白な問題があります。

  1. CFC 内のアプリケーション/セッション スコープに依存しているため、グローバル変数に依存する必要があります。これは init() メソッドがとりわけ使用されるものであり、init(datasource, provider_id, ext_ref_id, tstamp)それらをスコープに格納variables.できるため、CFC の外部で未定義の変数に対して脆弱ではなくなります
  2. リモートアクセスが許可されたcfcで、エスケープなしでLOTのVARCHARフィールドを使用しています。これは、SQL インジェクションに対して非常に脆弱です。Mr Bobby Tables は、なぜこれが悪いのかを教えてくれます ( http://bobby-tables.com/ )
  3. 文字列値 NULL を使用し続けます。これを varchar/quotes 内のデータベースに渡すと、データベースの NULL 値ではなく「NULL」として保存されます

全体として、最善の方法は、このコンポーネントを書き直すことです。コンポーネントを使用するすべてのコードの変更は、init() を追加する必要があり、いくつかの引数を削除する必要がある点まで最小限に抑えられますが、安定性が向上し、すべてがうまくいけば、この奇妙な問題は解消されます。

于 2012-04-17T08:28:39.983 に答える