Entries Tagged as 'Model-Glue'

Technique For Managing Form Input in Model-Glue

ColdFusion , Model-Glue No Comments »

I've been meaning to post about this technique I'm using in some of my Model-Glue applications, but I couldn't decide on the best way to explain what led me to develop it.  So I'm going to start with the code first rather than the explanation:

<cffunction name="collectFormDataAndTrim" access="public" returntype="void" output="false" hint="I collect the form values">
    <cfargument name="event" type="any">
    <cfset var loc= StructNew()>
    
    <cfset loc.propertyList= arguments.event.getArgument("propertyList","")>
    <cfif loc.propertyList EQ "">
        <cfset loc.propertyList= arguments.event.getValue("fieldnames")>
    </cfif>
    
    <cfset loc.form= StructNew()>
    <cfloop index="loc.prop" list="#loc.propertyList#" delimiters=",">
        <cfset loc.propValue= arguments.event.getValue(loc.prop)>
        <cfif IsNumeric(loc.propValue)>
            <cfset loc.form[loc.prop]= loc.propValue>
        <cfelse>
            <cfset loc.form[loc.prop]= Trim(HTMLEditFormat(beans.miscService.removeMSWordChars(loc.propValue)))>
        </cfif>
    </cfloop>
		
    <cfset arguments.event.setValue("form",loc.form)>
</cffunction>

 

This collectFormDataAndTrim function lives in my main controller CFC in my Model-Glue appplications. I call it via a message broadcast any time I need to process typical form input.

Like many of the ColdFusion application frameworks, Model-Glue takes both the URL variables and any values submitted by an HTML form and puts them into one data structure for easy retrieval.  In the case of Model-Glue, that data structure is the event object. My function supports two different methods for retrieving the form values from the Model-Glue event object: it can use the list of form field names contained in the "fieldnames" variable created by ColdFusion, or it can process the event variables named in an argument called "propertyList" submitted in the message broadcast, like so...

<broadcasts>
    <message name="collectFormDataAndTrim">
        <argument name="propertyList" value="firstName,lastName,email,acceptTerms" />
    </message>
...

 

Two reasons for the propertyList option: specifying the form fields you expect to get prevents you from processing extra form fields a malevolent user might add to the form via JavaScript or some other means, and it allows you to name checkbox fields which would not be included in the formfields list if the user doesn't check them.

Once the form fields names are copied into the local propertyList variable, the function loops through the form variables, sanitizes them for further processing using Trim() and HTMLEditFormat(), and adds them to the loc.form struct variable.  I also submit the non-numeric form values to the removeMSWordChars function in my miscService bean to replace any Microsoft Word characters within the content with web-friendly equivalent values (my users have an annoying habit of copying and pasting text from Word into longer text fields).

Finally, the loc.form struct variable containing the santized form submissions is saved back into the Model-Glue event object to be utilized by subsequent message broadcasts (for the functions that will validate the form data and save it to the database).

Preventing CSRF Attacks Using Event-Types in Model-Glue

ColdFusion , Model-Glue 1 Comment »

A cross-site request forgery (CSRF) occurs when a hacker takes advantage of the fact that users don't always log out of the websites and web applications they visit. The hacker creates a URL or a form that passes valid data to a valid destination on the target website and hopes that a user who is still authenticated to that website clicks that malicious URL or form. If such a user falls into the trap, the target website will process the request just as if the user had executed the action within the target website under normal circumstances.

One common method for preventing CSRF attacks is to generate a unique value every time a user visits a form on the website and store that value both within the user's session and within the form itself as a hidden field. When the form is submitted, the value in the form is checked against the value stored within the user's session, and if they don't match the form submission isn't processed. The next time the user encounters a form (even if it's the same form), a new unique value is generated. Without a way of knowing what that unique value is at any given time, the hacker cannot build a form or construct a URL that simulates a legitimate request, and the attack fails.

Rather than have to remember to create these unique values and include them within every form (or every URL that executed some sort of data operation), and then check the validity of the submitted value on each processing page, I wanted to see if there was a way I could build CSRF security into the structure of my Model-Glue applications.

Read more...

Quick Tip: Securing Your Model Glue XML Configuration Files

ColdFusion , Model-Glue 2 Comments »

A quick disclaimer: nothing I'm about to say here is all that revolutionary.  Others, particularly Charlie Griefer, have posted about this technique before, just not with a specific focus on using it with Model-Glue or with exact step-by-step instructions.

There are a number of key configuration files in Model-Glue that exist as plain XML files. One of the drawbacks to using XML files on a website is that anyone can point their browser at the XML file and read its contents, which is less than ideal from a security standpoint.

There are a number of ways you can make those XML files secure, such as storing them in a directory outside of the web root or configuring your web server to block access to XML files (see Charlie's post for details on those techniques), but not every developer has the permissions needed to implement those solutions.

So one way that you can protect those XML files without needing access to anything beyond the web root is to convert them to .cfm files and prevent them from executing, and here are the exact steps you would use in a typical Model-Glue application to do just that:

  1. Go to the index.cfm file of your application.  Uncomment the <cfset> line for "CUSTOM APPLICATION CONFIGURATION" and set it to point to "Coldspring.xml.cfm" instead of "Coldspring.xml".
  2. Rename "ColdSpring.xml" to "ColdSpring.xml.cfm". 
  3. In the ColdSpring file, go to the ModelGlue configuration bean definition and change the "configurationPath" and "scaffoldPath" values to point to the .cfm equivalent files instead of the original XML ones.  If you're using Transfer or Reactor in your application, also update any <constructor-arg> tags in those bean definitions that point to the XML configuration files for those ORM frameworks.
  4. If you have any other references  to .xml files in your ColdSpring file, update those as well.
  5. In the ModelGlue.xml file in your application, remove "<cferror>" from the comment above the "page.error" event (if you don't, anyone who does try to browse to that file will generate a ColdFusion error).
  6. Tack on ".cfm" to the file names of all of the .xml files referred to in steps 3, 4, and 5.
  7. Add an Application.cfm file to the "config" directory of ModelGlue with one line in it: <cfabort />  That will ensure that the XML is not shown even in the page source if the .xml.cfm file is directly accessed by the browser.

The end result of taking these steps is that if anyone tries to point their browser to any of these renamed configuration files (ModelGlue.xml.cfm, ColdSpring.xml.cfm, etc.) all they will get back is a blank page with no source code to view.

Creating a Reload Event-Handler for Model-Glue

ColdFusion , Model-Glue 1 Comment »

The Model-Glue framework has a number of configuration settings that modify its behavior. Perhaps the most important of these settings is the "reload" setting. When the reload setting is set to "true", the framework itself will be reload on each request, and any changes you made to the Model-Glue, ColdSpring, or ORM settings of your application since the last reload will be implemented. When reload is set to "false," those framework files will not be reloaded, and any changes you might have made to them are ignored.

So the idea is that you would have the reload setting set to "true" during development so that any changes you make are processed in the next request. The drawback to being in this constant-reload mode is that it takes time to reload the framework, an amount of time that increases as you add event handlers, message broadcasts, and such to the ModelGlue.xml file and add more bean definitions to your ColdSpring file. It's for this very reason that the Model-Glue team state that it is "imperative" that you set reload to "false" when you put your application into production.

As the development of your application progresses, you'll reach a point where you don't want to reload the framework for every single request because you're spending too much time waiting between requests. At that point, you would set reload to "false", and manually force a reload of the framework when necessary by adding the reloadKey and reloadPassword to the URL of one of your page requests, like so:

http://www.myModelGlueApp.org/index.cfm?init=true

...where "init" is the reloadKey and "true" is the reloadPassword.

Many Model-Glue developers open a separate tab in their web browsers pointing a URL for their application that contains the reloadKey and reloadPassword and simply reload that page whenever they need the framework reloaded, rather than navigating away from the current page they're working on. I decided to go a slightly different route and create a reload event-handler that I could trigger from any page in my Model-Glue application and execute the reload event in a new browser tab or window.

The page layouts of my applications always include some sort of header area at the top of the page. In the header area, I added a hyperlink labeled "Reload MG" with a URL pointing at my reload event-handler:

<cfif viewState.getValue("appEnvironment") EQ "local">
    <cfset reloadURL= viewState.getValue("myself") & "performReload&init=true">
    <p align="right"><a href="#reloadURL#" target="_blank">Reload MG</a></p>
</cfif>

In my last blog post, I explained how my applications determine whether they're running in my local development environment or my remote production environment. The <cfif> statement ensures that the reload link only appears in the header when I'm running the application on my local box. Having the "target" of the hyperlink set to "_blank" ensures that the reloader page opens in a new tab or window.

The performReload event-handler is defined in the ModelGlue.xml file like so:

<event-handler name="performReload">
    <broadcasts />
    <results />
    <views>
        <include name="body" template="util/dspReload.cfm" />
    </views>
</event-handler>

The reload action is initiated by the presence of the reloadKey and reloadPassword in the URL, so there isn't a need to execute any additional controller or model code. The event-handler simply loads the dspReload.cfm page in my "util" directory. This is what the dspReload.cfm page looks like:

<h2>Page Should Close Automatically</h2>

<script type="text/javascript">
    window.close();
</script>

The single Javascript statement is pretty self-explanatory: close the current window.

So when I click on the "Reload MG" link at the top of any of my Model-Glue application pages, a new browser tab opens and the focus of the browser is on that new tab. I can return to my previous tab (where I'm working) and simply wait for the reload event to complete over in the new tab. Once it does complete, the Javascript executes and the new tab is closed: I don't have to close it myself.

So instead of keeping an open browser tab that I'd have click on, click the reload button for, and the click back to my previous tab, I can just click a link in my current page to spawn a reload tab and simply navigate back to my original tab. While it's not a huge improvement, I prefer it over maintaining a reload tab.

Managing Environment-Specific Application Settings Via A ColdSpring Bean

ColdFusion , ColdSpring , Model-Glue 1 Comment »

When I develop my ColdFusion applications, I work in two different environments. I develop the applications on my local machine, then deploy them to the server when I reach particular milestones or when it's ready for limited user testing. Even though I mimic the server environment as best as I can on my local machine, there are still certain aspects of the application that are different when it executes on the server. For example, my local machine isn't configured to send and receive e-mail, but I want my application (when it's running in production) to send out an e-mail when certain functions are executed.

What I used to do to solve this problem was to run a series of functions via the onApplicationStart() function in Application.cfc that would determine where the application was running (development or production), record that fact in an application-scoped variable called "locale", and then set a series of additional application-scoped variables based on what the current environment was. I would then code certain aspects of my applications, such as those responsible for sending e-mail, to examine the value of the application.locale variable to determine if certain function should execute and then use any other application-level settings necessary for the actual execution (like the e-mail address associated with the application).

I recently started using Model-Glue as my application framework, and since Model-Glue uses ColdSpring to manage some of its internal settings, I decided to revise my technique to take advantage of ColdSpring as well.

Here is the code of the appConfig.cfc I created for managing the application settings:

<cfcomponent displayname="appConfig" hint="I provide the configuration settings for the application dependent on where the application is running.">

<cffunction name="init" access="public" returntype="any" hint="I accept all of the possible setting configurations">
<cfargument name="universalSettings" type="struct" required="true" hint="A struct of all of the configuration settings that are true regardless of environment" />
<cfargument name="localSettings" type="struct" required="true" hint="A struct of all of the configuration settings for the local environment" />
<cfargument name="remoteSettings" type="struct" required="true" hint="A struct of all of the configuration settings for the remote environment" />
<cfset var loc= StructNew()>
<cfset variables.config= StructNew()>
<cfloop collection="#arguments.universalSettings#" item="loc.ukey">
<cfset variables.config[loc.ukey]= arguments.universalSettings[loc.ukey]>
</cfloop>

<cfset loc.env= determineEnvironment()>

<cfloop collection="#arguments[loc.env]#" item="loc.ekey">
<cfset variables.config[loc.ekey]= arguments[loc.env][loc.ekey]>
</cfloop>

<cfreturn this />
</cffunction>

<cffunction name="determineEnvironment" access="private" output="false" returntype="string" hint="I determine the application environment">
<cfif Left(cgi.cf_template_path,6) EQ "/Users">
<cfreturn "localSettings" />
<cfelse>
<cfreturn "remoteSettings" />
</cfif>
</cffunction>

<cffunction name="getConfig" access="public" output="false" returntype="any" hint="I return a config setting">
<cfargument name="configName" type="string" required="true" hint="The name of the configuration setting">
<cfreturn variables.config[arguments.configName]>
</cffunction>

<cffunction name="setConfig" access="public" output="false" returntype="void" hint="I set a config setting">
<cfargument name="configName" type="string" required="true" hint="The name of the configuration setting">
<cfargument name="configValue" type="any" required="true" hint="The value/data to store in the configuration setting">
<cfset variables.config[arguments.configName]= arguments.configValue>
</cffunction>

</cfcomponent>

The init() constructor function takes three structs as arguments: one that contains the universal application settings that are the same regardless of environment, one that contains the application configuration settings for my local/development environment, and one that contains the configuration settings specific to my remote/production environment. The universal settings are copied into the "config" struct in the variables scope, and then a call is made out to the determineEnvironment() function to determine the current application environment. The determineEnvironment() function uses the cgi.cf_template_path to determine if the current ColdFusion template is running on a Macintosh system (my work laptop is a Mac) and returns the name of the constructor argument that should be used to populate the rest of the "config" struct. The getConfig() function provides a means of retrieving the value of a configuration setting, while the setConfig() function allows you to change a configuration setting.

So populating this appConfig object with the correct application configuration settings is simply a matter of providing the three different configuration structs into the init() constructor argument. That's where ColdSpring comes into play: ColdSpring is ideal for managing and documenting the data and objects that need to be injected into singleton objects. Here is an example ColdSpring bean definition (within a ColdSpring.xml file) for the appConfig object:

<bean id="appConfig" class="myApp.model.csBeans.appConfig">
<constructor-arg name="universalSettings">
<map>
<entry key="ds"><value>myDatasource</value></entry>
<entry key="appName"><value>myApp</value></entry>
<entry key="approot"><value>/myApp</value></entry>
</map>
</constructor-arg>
<constructor-arg name="localSettings">
<map>
<entry key="locale"><value>local</value></entry>
<entry key="emailNotification"><value>false</value></entry>
<entry key="uploadDirectory"><value>/Users/Brian/Websites/myApp/fileRepo/</value></entry>
</map>
</constructor-arg>
<constructor-arg name="remoteSettings">
<map>
<entry key="locale"><value>remote</value></entry>
<entry key="emailNotification"><value>true</value></entry>
<entry key="errorSenderName"><value>myApp System</value></entry>
<entry key="errorSenderEmail"><value>myApp@domain.org</value></entry>
<entry key="errorDefaultSubject"><value>An error has occurred in the myApp system</value></entry>
<entry key="uploadDirectory"><value>/wwwroot/myApp/uploadedFiles/</value></entry>
</map>
</constructor-arg>
</bean>

As you can see, the ColdSpring bean definition contains three <constructor-arg> XML blocks, one for each argument to be passed into the appConfig.cfc during instantiation, and each constructor argument contains a <map> XML block that defines the struct variable for that argument.

What's the advantage of defining these settings in ColdSpring? Once the appConfig object is defined as a ColdSpring bean, I can inject an appConfig bean into any other singleton bean object I define in ColdSpring or retrieve appConfig from the ColdSpring beanFactory object (which is usually instantiated during application startup). Plus, Model-Glue makes it very easy to inject ColdSpring beans into any of your controller objects simply by passing a list of ColdSpring bean names into a "beans" attribute in either the controller's &lt;cfcontroller&gt; tag or the starting &lt;controller&gt; tag of the controller's XML block in the ModelGlue.xml file of the application (see the "How to Use Bean Injection" page on Model-Glue documentation site for more details on that).  And it makes sense to put my application configuration settings alongside the Model-Glue configuration settings in ColdSpring so there's only one file I need to refer to for my configuration data.

The end result? I end up with an appConfig object containing the correct application settings for the current environment that my code can retrieve variable settings from whenever a function's behavior is dependent upon the application environment.

This technique I've just outlined works for me because I'm a solo developer with only two application environments, a simple way of determining which environment an application is running in, and usually only a small number of environment-specific app settings to deal with. If you're working in a team or with multiple application environments, you made need a more robust approach.  One option you might want to consider is the Environment Config project on RIAForge.org. The project also lets you leverage ColdSpring to define environment-specific variables, but it provides more options for distinguishing between different application environments and more flexibility in how you structure and retrieve your application configuration information. It's still in beta at the moment, but it looks promising.