NO MORE CAREER
POLITICIANS!
Get Out Of Our House: Replacing congress with TRUE citizens!
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

best web hosting - top web hosting sites, thetop10bestwebhosting.com

Czech your Page Rank!
Check Page Rank of any web site pages instantly:
This free page rank checking tool is powered by Page Rank Checker service
Surf's Up!
Visit Egosurf.org and massage YOUR web ego!
My Score: 9,001
Doug's Books

Read (and recommend)

  • Men are from Mars, Women are from Venus
  • The Wisdom of Crowds: Why the Many Are Smarter Than the Few and How Collective Wisdom Shapes Business, Economies, Societies and Nations
  • Blink: The Power of Thinking Without Thinking
  • Head First Design Patterns
  • Transact-SQL Programming
  • What's So Amazing About Grace?
  • Just So Stories (Rudyard Kipling collection)

Reading

  • Prayer: Does it Make Any Difference?
  • Data Mining (Practical Machine Learning Tools and Techniques)
<< September, 2010 >>
SMTWTFS
1234
567891011
12131415161718
19202122232425
2627282930
Search Blog

Recent Comments
Re: Railo 3.1 on Windows Server 2008 and IIS7 - Part 3 of 3 (by Jon at 8/27 2:04 PM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Spacy at 8/24 3:46 PM)
Re: THE DAY CFUNITED DIED (by ComboFusion at 8/23 10:50 AM)
Re: My Grandpa (by Tasha at 8/10 4:29 PM)
Re: Just What IS a 'Service Layer', Anyway? (by dougboude at 8/02 10:10 AM)
Re: Just What IS a 'Service Layer', Anyway? (by Isaac at 8/02 2:25 AM)
Re: PayPal IPN Coldfusion CFC (by Soyestudiambre at 7/25 6:12 PM)
Re: PHP vs COLDFUSION (by Tony Garcia at 7/17 11:24 AM)
Re: PHP vs COLDFUSION (by dougboude at 7/14 8:45 AM)
Re: PHP vs COLDFUSION (by Lola LB at 7/14 5:51 AM)
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

09 November 2008
Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
wiring and autowiring

In the first post on this subject, I shared my 10,000 foot view of what pieces needed to go where in a Coldbox app in order to implement security. A lot of the code in that post was probably unfamiliar looking to many people (I know it would have been to me a couple of days ago!). So in this post I want to share how I implemented Transfer and Coldspring in the security process, clarify what some of that code was doing, and whatever other details about it I may have also come to know.

I'm assuming that you already know what Coldspring is, what Transfer is, and the basics of an event-driven framework. For example, Coldspring is a framework that allows you to manage the relationships between your CFCs (CFC A needs a configuration bean injected into it, the configuration bean needs to be initialized with parameter X, etc.); Transfer is an ORM framework that stands between you and your database (in a good way) and lets you write your code "sans SQL"; and the basics of event-driven frameworks is that they have core components built into them that allow you (via the methods they expose to you) to reach into their very soul and leverage "core functionality", like retrieving global configuration settings, retrieve system beans, etc. Okay, all that having been said, here's the dialogue I had with my frameworks in order to get them all on the same page of the workbook (Personification to be followed up with real code snippets, don't worry. It just helps me simplify things when I animate the inanimate.  ):

1. "Hey, Coldbox;(via Coldbox.xml.cfm...) I'm using Coldspring to manage my components for me. What's that? You'll make your configuration settings available to Coldspring to use in its XML configuration file? When you fire up Coldspring you'll go through its configuration XML and replace any curly-braced variables with matching values from your own configuration BEFORE you initialize Coldspring? Aw, that's sweet. Thanks!"

2. "Hey Coldspring;(via Coldspring.xml.cfm...) I'm gonna need you to produce a few objects from our host MVC framework's core, Okay? What objects would those be? Oh, well, I'll be needing the Coldbox factory object since that's how you'll need to retrieve the rest of the framework's objects for me. I'll need you to ask the Coldbox Factory for an instance of the Coldbox framework itself since it has all the core methods that many of my model object will need; and I'll want a discrete instance of the Coldbox SessionStorage plugin as well so that my model objects can access my app's persistent scope. Let's see, what else...oh yes, I'll be using an ORM, so i'll need you to produce an instance of Transfer via its own factory. And then I'll just tell you about my model objects as I get them added to the app. Thanks, Coldspring! You're a real bud."

3. "Hey Transfer,(via Transfer.xml.cfm...)  I got a whole BOATLOAD of database objects I need you to make available to me. It's a very, very long list, so just read through it at your leisure."

My frameworks are very good listeners and so once I figured out exactly how to say what I wanted to say, they complied fully with my desires. So let's look at how I made them understand, shall we?

Dialogue 1
Within the Coldbox.xml.cfm file, in the <Settings> section, I made sure the following settings were like so:

<Setting name="IOCFramework" value="Coldspring" />
<!--IOC Definition File Path, relative or absolute -->
<Setting name="IOCDefinitionFile" value="config/coldspring.xml.cfm" />
<!--IOC Object Caching, true/false. For ColdBox to cache your IoC beans-->
<Setting name="IOCObjectCaching" value="false" />

 

As far as the rest of that dialogue, as long as I make sure the setting exists within the Coldbox.xml.cfm file, Coldbox will automatically replace any curly-braced variables in my Coldspring.xml.cfm file for me. For instance, in my Coldbox.xml.cfm file in the <YourSettings> section, I have the following Transfer values:

<YourSettings>
 <Setting name="TransferSettings.datasourcePath" value="/emailmanager/config/datasource.xml.cfm" />
 <Setting name="TransferSettings.configPath" value="/emailmanager/config/transfer.xml.cfm" />
 <Setting name="TransferSettings.definitionPath" value="/emailmanager/model/definitions" />
</YourSettings>

You'll see in the Coldspring snippets below the variable placeholders that correspond to these settings; it'll make more sense there. 

 (Note: presently, only curly-brace variables found within a <value>${myColdboxSetting}</value> tagset will be replaced. Don't put curly-brace vars in your bean's class path, for instance, and expect them to work. There is a way to do this which I'm investigating now, but by default it does not.)

Dialogue 2
We informed Coldspring of several different things, so let's look at them a chunk at a time.
"...produce a few objects from our host MVC framework's core...Coldbox factory object...Coldbox framework itself...a discrete instance of the Coldbox SessionStorage plugin...." Here is the XML to accomplish the previous:

<bean id="ColdboxFactory" class="coldbox.system.extras.ColdboxFactory" />
<bean id="Coldbox" factory-bean="ColdBoxFactory" factory-method="getColdbox" singleton="true" />
<bean id="oSession" factory-bean="ColdBoxFactory" factory-method="getPlugin" singleton="true">
 <constructor-arg name="plugin">
  <value>sessionstorage</value>
 </constructor-arg>
</bean>


If you aren't familiar with Coldspring's ability to produce a bean by executing a method referenced on a previously defined bean, well, you're looking at it in action (note the 'factory-bean/factory-method' attributes). I myself wasn't aware of this ability, so was quite happy to have discovered it. First we're defining Coldbox's object factory; then we're creating an instance of Coldbox by calling the Factory's "getColdbox" method; lastly I'm grabbing an instance of Coldbox's built-in "sessionStorage" plugin the same way, calling the generic "getPlugin" method and passing in the name of the plugin I want.

Next portion of that dialogue...
"...I'll be using an ORM, so i'll need you to produce an instance of Transfer via its own factory...." Here's that code (notice the curly brace vars; each one equates to a setting created in the Coldbox.xml.cfm file): 

<bean id="transferFactory" class="transfer.TransferFactory" singeleton="true">
 <constructor-arg name="datasourcePath">
  <value>${TransferSettings.datasourcePath}</value>
 </constructor-arg>
 <constructor-arg name="configPath">
    <value>${TransferSettings.configPath}</value>
 </constructor-arg>
 <constructor-arg name="definitionPath">
    <value>${TransferSettings.definitionPath}</value>
 </constructor-arg>
</bean>

<bean id="Transfer" factory-bean="TransferFactory" factory-method="getTransfer" singleton="true" />
<bean id="Datasource" factory-bean="TransferFactory" factory-method="getDatasource" singleton="true" />

Defining Transfer's own factory, then defining the other Transfer beans as results of executing Transfer Factory methods. Noice, eh?

 

 As far as the model, so far I have only one bean defined, and that is my "authenticationService" bean. Here's that Coldspring.xml:

<bean id="authenticationService" class="emailmanager.model.services.authenticationservice">
 <constructor-arg name="transfer">
  <ref bean="Transfer" />
 </constructor-arg>
 <constructor-arg name="oSession">
  <ref bean="oSession" />
 </constructor-arg>
</bean>

As you can see, I'm passing in an instance of Transfer and Coldbox's session manager upon instantiation. By doing so, my service object can perform database calls and manage persistent values.

 

 Dialogue 3
Transfer relies on an XML file to get its information about your database entities (tables) and their relationships to one another. I won't share the entire Transfer.xml.cfm file here since I've already got most of my entities defined for my app (long list), but here are the tables relevant to security:

<objectDefinitions>
 <package name="user">
  <object name="user" table="appuser" >
   <id name="id" type="string" generate="false"/>
   <property name="username" type="string" column="username" nullable="false"/>
   <property name="password" type="string" column="password" nullable="false"/>
   <property name="firstname" type="string" column="firstname" nullable="false"/>
   <property name="lastname" type="string" column="lastname" nullable="false"/>
   <property name="email" type="string" column="email" nullable="false"/>
   <property name="isActive" type="boolean" column="isActive" nullable="false"/>
   <property name="timezone" type="string" column="timezone" nullable="true"/>
   <onetomany name="usergroup" lazy="true">
       <link to="usergroup.usergroup" column="userid"/>
       <collection type="array">
         <order  property="id" order="asc"/>
       </collection>
   </onetomany>
  </object>
 </package>
 <package name="usergroup">
  <object name="usergroup" table="usergroup" >
   <id name="id" type="string" generate="false"/>
   <property name="groupid" type="string" column="groupid" nullable="false"/>
  </object>
 </package>
</objectDefinitions>

Now that I have all of that set up, let me share again the code from my authentication handler(controller) and authenticationService cfc (that I shared in my previous post on this topic)  that peform the login function.

 

 authentication handler

<cffunction name="doLogin" access="public" returntype="void" output="false">
 <cfargument name="Event" type="any" />
 <cfset var loggedin = "" />
 <cfset var rc = arguments.Event.getCollection() />
 <!--- attempt to authenticate using the credential supplied... --->
 <cfset loggedin = variables.authenticationService.login(username=rc.username,password=rc.password) />
 <cfif not loggedin><!--- login failed...send them back --->
  <cfset arguments.event.setValue("loginmessage","Login Failed. Please try again.") />
  <cfset arguments.event.setValue("loggedin",false) />
  <cfset arguments.event.overrideEvent("login") />
 <cfelse>
  <cfset arguments.event.setValue("loggedin",true) />
 </cfif>
 <cfset arguments.event.setvalue("xe.frmAction","authentication.doLogout") />
 <cfset arguments.event.setView("login") />
</cffunction>

The line to home in on is the one that begins "<cfset loggedin = ...". It is there that, from within my handler, I am accessing the authenticationService bean we defined in Coldspring.xml.cfm. You'll recall though that I did NOT define a relationship between my handler and authenticationService. How then did my handler get access to it?

In Model-Glue, we would have provided our controller a setter and getter for the authentication service, then Model-Glue itself would have auto-injected that bean for us. Well, Coldbox to the rescue, we have the same type of functionality available to us! Coldbox actually allows two ways to auto-inject Coldspring-defined beans: via setters and getters, as we are probably accustomed to; and via the <cfproperty> tag. Now, typically cfproperty doesn't really do much for us at all; but in a Coldbox handler it's a big ol' flag that says "inject it here! inject it here!. Okay, here's the additional line in our authentication handler that performs this magic:

<cfproperty name="authenticationService" type="ioc" scope="variables" />

I opted NOT to go the setter and getter route because of the fact that if I happened to have created a setter and getter that had the same name as a bean i defined, it would attempt to auto-inject whether I really wanted it to or not. In order to avoid this, I am choosing to explicitly name my auto-injections via the <cfproperty> tag. 

Okay, so our doLogin event is calling the authenticationService's 'login' method, passing in the username and password supplied; Let's look at authenticationService now.

<cffunction name="init" access="public" output="false" returntype="any">
 <cfargument name="transfer" type="any" required="yes" />
 <cfargument name="oSession" type="any" required="yes" />
 <cfset variables._transfer = arguments.transfer />
 <cfset variables._session = arguments.oSession />
 <cfreturn this />
</cffunction>

<cffunction name="login" access="public" returntype="boolean">
 <cfargument name="username" type="string" required="yes" />
 <cfargument name="password" type="string" required="yes" />
 <cfargument name="isActive" type="boolean" required="yes" default="true" />
 <!--- create a transfer user bean, passing in the username and password, then give it back --->
 <cfset var objUser = variables._transfer.readByPropertyMap("user.user",arguments) />
 <cfset retval = false />
 <cfif objUser.getID() IS "0"><!--- login failed... --->
  <cfset variables._session.setVar("loggedin",false) />
 <cfelse>
  <cfset variables._session.setVar("loggedin",true) />
  <cfset variables._session.setVar("user",objUser) />
  <cfset retval = true />
 </cfif>
 <cfreturn retval />
</cffunction>

 We instructed Coldspring to inject Transfer and oSession into this bean upon creation, and made provision for it via the init method. Pretty standard Coldspring stuff. In our login method, we call upon Transfer to create for us the "user.user" bean, giving it our argument collection to use as criteria (my arguments are named exactly as fields in that table). Also, in case you're wondering why we didn't ask Transfer for the "user" bean instead of the "user.user" bean, it's because in our Transfer.xml.cfm file we defined a package called "user" and within that package an object named "user". Hence the path "user.user".

 

 So, Transfer will create the requested bean and, if it matched the criteria passed in, the bean will be populated; otherwise it'll be empty, with a zero value for the primary numeric key ("ID"). After Transfer gives it back, I check the primary key. If it's zero, login obviously failed. If it's not, success! Stuff the user bean into session and return a boolean to the handler (controller).

I do hope you were able to follow this okay. I can't tell you how long I had to bang my head against it for it to sink in and gel, so I hope it saves someone else a few hours of digging through docs.

Doug out.




Posted by dougboude at 1:58 AM | PRINT THIS POST! |Link | 7 comments
Subscription Options

You are not logged in, so your subscription status for this entry is unknown. You can login or register here.

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
What about using ColdBox's security interceptor? I created a security example, which makes use of transfer and lightwire. Take a look at the ColdBox samples.

Ernst
Posted by Ernst van der Linden on November 9, 2008 at 6:31 AM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
Ernst, I DID look at the example apps. Like I mentioned in the first post, they work great...but it took me a long time to dissect them to figure out exactly how they worked (as you know, there are little parts scattered here and there within the framework that compose the whole security event lifecycle). I more than likely will end up using the built in security interceptor, but the learning process dictates that I must understand how all these pieces fit together and work individually before I can confidently utilize more complex, 'out of the box' parts of the system. Everything I shared in this post and in the previous post is meant solely for the purpose of helping anybody else who's treading the same learning curve as I to get there just a little bit faster. What might be even more helpful is if you added some concise documentation to your sample apps that explain the nuances and intricacies of why your apps work like they do. Nothing overly verbose; in fact, maybe just a nice powerpoint diagram with clipart, labels, and arrows. :)
Posted by dougboude on November 9, 2008 at 12:40 PM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
I am gonna go with Doug here as well. Even though the documentation is there (and so much of it!), it's painful to go through all that and try to figure out why things are done like so. The major factor in stopping me from implementing this framework in my projects is a solid and complete website example with full source code, that I can take apart and analyze. Stand-alone examples that come with the installation are ok, but don't give a complete picture.
Posted by Evagoras Charalambou on November 10, 2008 at 3:26 AM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
@doug thanks for such a detail info on coldspring + transfer, to be honest we always spend many hours on documentation. I really like your article and will be great asset for others as well.

@Evagora having multiple small sample Apps are always a good idea, because each developer choice is different, for example some use LightWire, some ColdSpring, some no ORM, so in these cases we have to offer smaller different Apps to cover different flavour.

ColdBox wiki codexwiki is under private beta and I am sure soon you will see a bigger App in the near future.

Also Lightwire have new goodies as well, this will be release very soon, as sneek peek ability to define java object like this.
and much more. stay tune

Your feedback is always very important to us, so that we can improve/enhance the system to meet every body's needs.
Posted by Sana on November 11, 2008 at 6:57 AM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
Thanks, Doug, and I concur that while there is plentiful documentation, in the sense of many texts, there is a dearth of "build-ups", lets start with a bare-bones and add security to it, add IOC to it, add SES to it.
I understand that everyone needs something slightly different, but it seems to me that every example expects us to reverse-engineer out what parts are unique to it and its functionality and which are the framework.
OK, I'm a newbie to ColdBox, an experienced ColdFusion (since 0.82, remember "" tags?) programmer, and just completed an enterprise application in FuseBox 5. So I'm trying to balance my excitement at this rich framework with, as Doug says, some gathering of intelligience before trying to move an intranet application from FuseBox to ColdBox!
Posted by orc on December 8, 2008 at 11:44 PM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
Your posts helped me in a great way of understanding what's happening. Thanks alot!
Posted by RichardH on September 8, 2009 at 2:58 AM

Re: Basic Security in Coldbox using Transfer and Coldspring - Part II (of II)
@RichardH - No problem, Richard, glad to share what I learn. Pay it forward! :)
Posted by dougboude on September 8, 2009 at 9:26 AM

Name:   Required
Email:   Required your email address will not be publicly displayed.

Want to receive notifications when new comments are added? Login/Register for an account.

Time to take the Turing Test!!!

20 plus 6 equals
Type in the answer to the question you see above:

Your comment:

Sorry, no HTML allowed!