Categories
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

<< June, 2013 >>
SMTWTFS
1
2345678
9101112131415
16171819202122
23242526272829
30
Search Blog

Recent Comments
Re: Disappearing IE Popup Window During Save/Open Dialog (by LZ at 4/20 7:58 AM)
Re: Create Dynamic WHERE Clauses in PHP (by pooja at 3/20 7:29 AM)
Re: Just What IS a 'Service Layer', Anyway? (by EugenK at 3/07 7:56 PM)
Re: Using Google as your CF Mail Server (by 5starwebteam.com at 2/25 1:27 AM)
Re: Why Provide for Service layer objects in CFWheels? (by Steven Benjamin at 1/25 11:43 AM)
Re: What is an 'Advanced' Coldfusion Developer? (by ColdFusion Developer at 12/24 5:14 AM)
Re: Equivalent of SQL "TOP X" in Oracle (by Ashenafi Desalegn at 12/06 5:29 AM)
Re: PHP Export to Excel Snippet (by serene at 12/05 1:44 AM)
Re: Just What Is 'Application Logic', Anyway? (by Arif at 11/13 8:06 AM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Aaron at 10/22 2:31 PM)
Re: PHP Export to Excel Snippet (by Jafar Shah at 10/10 4:28 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Chenelle S at 10/04 12:53 PM)
Re: PHP Export to Excel Snippet (by Kilo at 9/26 5:20 PM)
Re: Porting Coldfusion Code to Mura (by tariq at 9/03 9:51 AM)
Re: Just What IS a 'Service Layer', Anyway? (by James at 8/27 4:06 PM)
Re: Calculating Business Hours (by helen at 8/14 2:54 AM)
Re: What IS 'Business Logic', Anyway? (by dougboude at 8/06 11:30 AM)
Re: What IS 'Business Logic', Anyway? (by Adrianne at 8/06 10:29 AM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by dougboude at 8/04 4:39 PM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by Lola LB at 8/04 7:43 AM)
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

03 July 2008
Basic Security in Fusebox 5.5.x (sans XML)
I have recently begun a project using the latest version of Fusebox (5.5.1). This is my second forray into Fusebox 5x, but the first one wasn't much more than a hello world for my own benefit. This time, I'm taking the "sans XML" approach and using FB in its MVC arrangement to build an application that is primarily a data management tool utilizing Java proxies exclusively as its means to communicate with a backend Oracle database. So, as I learn things along the way, I'm going to be sharing them as blog posts in order to possibly give others some stepping stones as they traverse their own FB "sans XML" J-curve.

I should also say that I am coming to Fusebox 5.5 after having exclusively used Model-Glue v2 for the past year and a half or so. Since one's natural approach is to try and equate what you already know from your current framework of choice to the one you are now learning, that is what I will be doing as well, so you may often see me reference things in Model-Glue terminology to help bridge the knowledge gap. In fact, one of the first things I did was to rename my fuseaction to "event", just to make me feel a little more at home. :)

Okay, so one of the first things I needed to create for this app was some basic security; if the user is not logged on, they don't get past the first page, period. Though there are always many solutions to the same challenge, following is my own approach to the matter.

Step 1 is find the best place within the Fusebox event lifecycle (which I STILL don't fully know, nor could I find any clear documentation on) in which to "intercept and potentially redirect" our call. Basically, before our user arrives at their destination page, we want to see if it is a secured page (which all of mine are except for the login) AND if the user has already successfully authenticated, then redirect them to the login page if needed.

In order to maintain the user's state (keep track of whether or not they logged in, store their personal info in a handy, globally available package), I created a User.cfc that I make sure has been instantiated with an initial 'loggedin' setting of false (this is built into the CFC's init method), and placed into the session scope. In Fusebox 5.5.1, the most appropriate place to do this that I found is in the Application.CFC's "onRequestStart" method. Mine looks like this:

<cffunction access="public" name="onRequestStart" output="false" returntype="void" hint="I am the code to execute at the beginning of a request. ">
    <cfargument name="targetPage" />
    <cfset super.onRequestStart(arguments.targetPage) />
    <!--- formerly in fusebox.init.cfm --->
    <cfset self = myFusebox.getSelf() />
    <cfset myself = myFusebox.getMyself() />

    <cfif not structkeyexists(session,"user")>
        <cfset session.user = createObject( 'component','model.user').init()/>
    </cfif>
   
    <!--- making our user object available in the event bean. Event is created by Fusebox and is available to us at this point. --->
    <cfset event.setValue("user",session.user) />
</cffunction>


Notice that we are doing a call to "super.onRequeststart". This is because our Application.cfc is extending (<cfcomponent extends="fusebox5.Application" output="false">) Fusebox's Application.cfc, so we need to make sure the framework gets to execute its onRequestStart as well. If we didn't make the 'super' call, our method would override FB's method and things just wouldn't go well at all.

Okay, so now with every request, I ensure that I have at LEAST an empty user object in session. The remainder of the onRequestStart method places my user object into a handly little bucket Fusebox provides us called (thankfully) 'Event'. This works very well for me, as in Model-Glue it's ALL ABOUT the event, my brutha from anotha mutha. By putting user into 'event', i can access it from anywhere else in my application WITHOUT having to talk directly to session ( a big OO No No, for the most part).

Now, the request still has not yet arrived at its destination page, and Fusebox has another file yet to process before it renders any content: Fusebox.init.cfm.

Though I tried madly to do all of my intercept and redirect within application.cfc, alas I could not make it work. Feedback from Mr. Corfield affirmed that indeed application.cfc was not the best place to do what I was trying to do, anyway, and directed me to fusebox.init.cfm as the most proper location to perform any needed manipulation of the target fuseaction. Here is the content of my fusebox.init.cfm file:

<!--- ************ SECURITY CHECK! ***************** --->
<!--- if we're not authenticated and our current fuseaction is NOT our default fuseaction (in order to avoid a dreaded infinite loop), make it so --->
<cfif (not structkeyexists(session,"user") OR not session.user.getLoggedin()) AND attributes.fuseaction IS NOT myFusebox.getApplication().defaultfuseaction>
    <!--- if user is not logged in, replace the current fuseaction/event name with our default --->
    <cfset myFusebox.relocate(url=myFusebox.getApplication().myself & myFusebox.getApplication().defaultfuseaction) />
</cfif>



As you can see, i'm doing a simple check of the user object and the target fuseaction. If the user isn't logged in (or user object doesn't exist for whatever reason) AND our target fuseaction is something OTHER than our default fuseaction (login), then we're leveraging the fusebox 'Relocate' method to force the user to our login page.

That's it, it's that simple. If I had to do fuseaction level security, or individual page security, I think I'd probably STILL perform those actions at these exact same locations, only I'd be adding in additional checks for the user's roles and the fuseaction's security level.

Feedback on my approach solicited. :)

Doug out

 

UPDATE TO PREVIOUS POST (7/9/08)

Based on the comments I received, I made a little time to pursue the route I had proposed for implementing role/fuseaction based security and found that I could do it easily without having to add any more controllers or fuseactions. Building on all of the code above, I simply added to my user object a 'Roles' variable that contains a list of the authenticated user's roles. I then added to my global configuration bean an item 'publicFuseActions' that contains a list of the fuseactions I am NOT securing (since those are far fewer than the ones I AM securing...I could've easily reversed the contents of this list to contain FAs that ARE secured). Lastly, I made a modification to the security check in my fusebox.init.cfm to evaluate the following:

(

the user is NOT logged in

OR

user IS logged in AND the requested fuseaction IS a secure one AND the authenticated user does NOT have the appropriate role

)

AND

our requested fuseaction is NOT our default fuseaction

If the entire statement above evaluates to true, then our user needs to be redirected to the login page.

Here is my fusebox.init.cfm that accomplishes the above logic:

 

<cfif ((not structkeyexists(session,"user") OR not session.user.getLoggedin()) OR (listfindnocase(application.globals.config.getConfigSetting("publicFAs"),attributes.fuseaction) eq 0 AND listfindnocase("Admin",session.user.getRoles()) eq 0)) AND attributes.fuseaction IS NOT myFusebox.getApplication().defaultfuseaction>
 <cfset myFusebox.relocate(url=myFusebox.getApplication().myself & myFusebox.getApplication().defaultfuseaction) />
</cfif>

 

Again, I have to ask what would be the motivation/need to create additional controllers and fuseactions to perform security/role based fuseaction routing when the single IF statement above, strategically placed, accomplishes it just fine? Am I over-simplifying things? (or is it really just that simple?  ) . If I wanted to get even more elaborate, such as routing based on role, or a diversity of messages to match the situation, I would probably add a message dictionary to my global config bean and replace my growing IF statement with a call to a global security object that would perform appropriate evaluations and return the needed responses for me to execute an appropriate redirect and message. One more object in my model that I create as a singleton and have available to my fusebox.init.cfm...why complicate it any more than that? Again, input solicited.

Doug out. again.

 




Posted by dougboude at 1:51 PM | 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 Fusebox 5.5.x (sans XML)
Here's my $0.02 on how I would handle your site security.

I would have 2 'controller' circuits. The first one would be the default 'app' circuit. This circuit would have 2 Fuseactions: 1) Show the home page (which has a login form), and 2) Authenticate Login (which validates the credentials).

I would then create an additional circuit (let's call it 'foo') that contains all of the really important fuseactions for your site. In the /controller/foo.cfc file, I would then have a function named 'prefuseaction' which checks to ensure the user has logged in properly. If they haven't, then they would get redirected back to the home page.

The 'prefuseaction' function in your foo.cfc file will execute prior to any fuseaction in the foo circuit. I hope that helps!
Posted by Damon Gentry on July 3, 2008 at 2:35 PM

Re: Basic Security in Fusebox 5.5.x (sans XML)
@gentry: forgive my naivetee, but isn't that a lot more work and code? Just curious, but what's the justification for the additional controllers and code? What's the payoff? What does it allow me that I need and don't have with my approach? I'm sincerely interested! And thanks for the alternative suggestion!
Posted by dougboude on July 3, 2008 at 7:31 PM

Re: Basic Security in Fusebox 5.5.x (sans XML)
@Doug
I wouldn't say its a lot more work to do what Damon suggested.

The payoff would be a controller that anything you didn't need a security check could go into. just shooting blindly, i would say your home page, your login page, later when/if you add a privacy statement or something along those lines. And, this wouldn't require a change to your security check.
Posted by Matt Jones on July 7, 2008 at 1:16 PM

Re: Basic Security in Fusebox 5.5.x (sans XML)
I don't see anything wrong with the way you are doing it.

The extra controllers for me I see as extremely simple, and use them to group code into a ... for lack up a better word, "module". In my scenario a controller is for a module and public just happens to be one of those.

The important thing of note though is probably that while fusebox 5.5 noxml is limited in how it can accomplish some things (I actually find this to be a good thing) compared to its xml brother, there are still many ways to solve the problem.

Having a solution is really what matters in the long run, and even better if that solution is one you are comfortable with.
Posted by Matt Jones on July 9, 2008 at 10:07 AM

Re: Basic Security in Fusebox 5.5.x (sans XML)
"...primarily a data management tool ...communicate with a backend Oracle database."

You might want to have a look at what Steve Bryant is doing with his CFC called DataMgr. I just tested it out in a FB5.5 application, and it worked really nicely. Saved me quite a bit of time by not having to write all that SQL code with CFPARAMS in it. Anyway, his tool can "communicate" with Oracle, so it might be worth checking out.

DataMgr:
http://www.bryantwebconsulting.com/blog/index.cfm/2008/7/25/DataMgr-22-Beta-1
Posted by Jeff Knooren on August 8, 2008 at 7:06 AM

Re: Basic Security in Fusebox 5.5.x (sans XML)
Hi Doug,

Im new to FB and CF and for the last few days ive been trying to do something similar to what you're describing in this post with zero success, strangely there are no tutorials on how to build login security in FB5.5. I would very much appreciated it if you can help me.

I have a few questions based on your tutorial as im not sure what some of the functions are supposed to do;

I know this is tutorial is old, im not sure its is still valid, the FB skeleton ive downloaded does not contain fusebox.init.cfm, shall i just create one into the root of my application?
What would the the function session.user.getLoggedin do? Would it run a query, if session.user.userId exists return userDetails otherwise returns false?
What would the the function session.user.getRoles do? Would it run a query, if session.user.userId exists return userRollDetails otherwise returns false?
Where is the global configuration bean and would is just list a bunch of fuseactions in the publicFAs var?

Hope you're able to help me.

Thanks
Posted by dlaws on May 18, 2010 at 3:15 AM

Re: Basic Security in Fusebox 5.5.x (sans XML)
@dlaws...
this was a while back for me, but i'll try to elaborate on the questions you have...

The fusebox.init.cfm ... I haven't touched the FB framework since I did that post, so I'm not sure what fusebox.init.cfm has morphed into these days! What you're looking for, though, is the place within the Fusebox event lifecycle that occurs "onrequeststart", or a similar interception point, so that you can decide whether to redirect the user or not BEFORE they attempt to access the requested fuseaction.

My user object's getLoggedin method simply returned a true or false, depending on whether or not authentication had successfully taken place or not. Just a flag.

getRoles would return a structure of role IDs and role Names that was populated when the user authenticated. Typically, my authentication consists of a query joining my user table to the roles table. If the passed in credentials were valid my resulting query will contain both the user info and the user's roles. I then typically transfer the roles data out to a structure and store it in the user object's variables scope.

global configuration bean...my global config beans typically contain values such as DSN name, paths to my images folder, JS files, mail server name, and in the case of securing specific events, I would maintain a list of either public or secured fuseactions. Such config beans I maintain as a singleton in the application scope.

Hope this helps a little. Are you a member of the Fusebox list? I'm sure you could get some input there as to what has superceded the fusebox.init.cfm file since 5.5
Posted by dougboude on May 18, 2010 at 10:12 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!!!

Fourteen plus Three equals
Type in the answer to the question you see above:

Your comment:

Sorry, no HTML allowed!