cfFormProtect mit Model-Glue verwenden

Mischa Sameli, Geschäftsführer & Leiter Entwicklung

Für ein Projekt mit Model-Glue habe ich mich entschlossen, die Anti-Spam-Bibliothek cfFormProtect zu integieren. Nachträglich versteht sich. Nachträglich, da alle Formulare bereits bestanden haben. Zur Erstellung und Validierung der Formulare habe ich zwei anderen Open-Source-Bibliotheken eingebaut: cfUniForm und ValidateThis!. Wie einfach liess sich nun die Anti-Spam-Massnahme integrieren?

Einfach, um es gleich vorweg zu nehmen. Was es alles braucht:

  1. Controller mit zwei Funktionen
    1<cffunction name="loadFormProtect" output="false" access="public" returntype="void" hint="">
    2<cfargument name="event" type="any" />
    3<cfset arguments.event.setValue("cffp_config", getModelGlue().getBean("cfFormProtect").getConfig())>
    4</cffunction>
    5<cffunction name="testFormProtect" output="false" access="public" returntype="void" hint="">
    6<cfargument name="event" type="any" />
    7<cfif Not getModelGlue().getBean("cfFormProtect").testSubmission(arguments.event.getAllValues())>
    8<!--- The test failed. Take appropriate failure action here. --->
    9<cfset arguments.event.addResult("spam","true")>
    10</cfif>
    11</cffunction>
  2. Funktionen im ModelGlue.xml registrieren
    1<controller name="mainController" type="controller.Controller">
    2<message-listener message="load.cfFormProtect" function="loadFormProtect" />
    3<message-listener message="test.cfFormProtect" function="testFormProtect" />
    4</controller>
  3. Ein View für die Formfelder definieren Die Datei cffp.cfm der Bibliothek kann mit wenigen Anpassungen direkt als View verwendet werden. Mit dem Event "load.cfFormProtect" laden wir die Konfiguration und speichern diese in die Event-Variable "cffp_config" (siehe 1.). Diese Variable verwenden wir nun im View:
    1<cfset cffpConfig = viewstate.getValue("cffp_config","")>
    2<cfif isStruct(cffpConfig)>
    3<!--- Original-Code --->
    4</cfif>
    Nun können wir die Bibliothek bereits verwenden, respektive, wir haben alle Komponenten die wir brauchen. Der Einbau in ein Formular sieht dann etwa so aus.
  4. Event für das Formular ergänzen
    1<event-handler name="user.edit">
    2<broadcasts>
    3<!-- neu: load.cfFormProtect -->
    4<message name="load.cfFormProtect" />
    5<message name="adminkunde.edit" />
    6</broadcasts>
    7<views>
    8&#60;include name="nav" template="content/navFormAllgemein.cfm">

    9<value name="xe.add" value="user.add" />
    10<value name="xe.back" value="user.list" />
    11</include>
    12<!-- neu: view frmCFFP -->
    13&#60;include name="frmCFFP" template="content/frmCFFP.cfm" />
    14&#60;include name="dataform" template="content/frmUser.cfm">
    15<value name="xe.formtarget" value="user.save" />
    16</include>
    17</views>
    18<results>
    19<result do="view.admintemplate" />
    20</results>
    21</event-handler>
    Wie man sehen kann, wurden hier gerade einmal zwei Angaben ergänzt: der Broadcast und ein View.
  5. Form anpassen Das Formular muss auch noch geringfügig angepasst werden. Und zwar muss innerhalb des Form-Tags folgender Code plaziert werden:
    1<cfif viewCollection.exists("frmCFFP")>
    2#viewCollection.getView("frmCFFP")#
    3</cfif>
    So nun werden alle notwendigen Scripts und Formfelder integriert. Die Validierung schliesslich ist noch einfacher gelöst, denn dafür muss ausschliesslich das ModelGlue.xml angepasst werden.
  6. Und zwar fügen wir lediglich einen weiteren Broadcast und eine Result-Variante hinzu
    1<event-handler name="user.save">
    2<broadcasts>
    3<!-- neu: test.cfFormProtect -->
    4<message name="test.cfFormProtect" />
    5<message name="user.save" />
    6</broadcasts>
    7<views />
    8<results>
    9<result do="user.edit" name="failed" redirect="false" />
    10<!-- neu: result spam -->
    11<result do="home" name="spam" redirect="true" />
    12<result do="user.list" name="success" redirect="true" />
    13</results>
    14</event-handler>
    Wenn nun ein Spam entdeckt wird, wird gemäss der Controller-Funktion (Punkt 1) die Result-Variable "spam" gesetzt. Und dies führt wiederum sofort dazu, dass der result-Event "spam" ausgeführt wird. Der Broadcast "user.save" wird gar nicht mehr aufgerufen. Das spart auf der einen Seite natürlich Performance und erleichtert das Coding, da nicht noch manuell auf die Result-Variable geschaut werden muss. Auf der anderen Seite kann man nun ohne weiteres die Spam-Detection wieder entfernen, indem man einfach beim Event "user.save" den Broadcast auf "test.cfFormProtect" entfernt. Weitere Anpassungen sind nicht mehr nötig.
  7. Im Übrigen hat es länger gedauert, diese Zusammenfassung zu schreiben, als die Bibliothek einzubauen…