Michael asks:
We are inheriting a ColdFusion application written in ColdFusion. This application is be modified by us to conform to our business process. Our current application is written in PowerBuilder.
The crux of the question is it possible to implement complex security. By complex each page needs to have business rules to a specific user/role. IE some users will need to be allowed to perform a specific function some not. Some will need to see certain parts of the page some not. Some buttons will be enabled some not etc.
All of the examples that I am seeing in relation to security is based on hackers trying to infiltrate the system not controlling the actions of the users using the system base on a role.
Is this realistically possible with ColdFusion? I have been investigating Ajax, but I am to much a CF newbie to make a determination as this time.
You've got a lot here so let me try to break this up into a few sections.
So first off - you are right - if you search for security you will most likely find articles talking about blocking hacking attempts. I'm not even quite sure the best way to describe the difference between that and what you are talking about. One is more attack prevention and one is more business rule security. So I'll start off this response with a plea to my readers to provide any URLs they may know of. I did a quick search at Charlie Arehart's UGTV site (http://www.carehart.org/ugtv/index.cfm) and found 7 results, but these don't seem to be exactly what you want either.
Turns out I actually have a presentation on the topic - but it's rather simple. You can find the Connect recording here and the associated files here.
What this really boils down to is having ColdFusion understand authorization and authentication. Authenticating is simply proving that the user is who they say they are. This is normally done via database queries, which ColdFusion makes trivial. You may also do it via LDAP - which again is trivial in ColdFusion.
Authorization is a bit more tricky. You talked about users and roles and how some users could do X, see Y, etc. In general it might make sense to simply think of these both as actions on resources. So for example:
User A has the right to VIEW a page that is RESOURCE 5.
User B has the right to VIEW a page that is RESOURCE 4.
User C has the right to VIEW,EDIT a page that is resource 5.
In the above list, you see 3 users and their permissions. The text in capitals refers to both the action they can do (view, edit, etc) and the resource. The action could be anything. In general it tends to boil down to viewing, editing, creating, and deleting. The resource can be anything to - and generally matches the database. So for Amazon the resources could be books, CDs, movies, etc.
So really this comes down to having ColdFusion recognize who you are (authentication) and authorizing you when you do an action. How you implement this is a matter of personal preference. If you download Galleon you can see one example. In Galleon, users can have VIEW, POST, and EDIT permissions in forums. I stored a table of things you could do (galleon_rights) and a store of who could do (galleon_permissions). The permissions table basically said that a group X could do right Y on a resource (thread). In Galleon I took a simpler route where permissions are only associated with groups, not individual users, but this simpler view worked fine for the application as everyone is in a group.
So I guess the upshot is that - yes - it is possible. The implementation though is really going to come down to your exact business rules. I've linked to one of my presentations and one of my open source applications, and my readers will add to this as well.
Archived Comments
I've built similar functionality (at least for the Model) by using ColdSpring's AOP capabilities. So the questioner may want to look into that as a possible option.
An approach I've taken over the years is to create segments which can be anything from a link on a page to a whole file or even directory. This allows anything to be defined for security purposes.
Then users get assigned segments, often via groups, and when they log in these segments get put into session scope. Then each segment checks to see if the user has that segment and if so provides access and if not takes some action. This action can vary from a complete no access to showing something else to showing nothing at all.
I've been looking for exactly the same thing. Any help would be appreciated. I also got too many other results when looking for security.
Either I'm oversimplifying things or am misunderstanding the post, but why not use <cflogin> and its built-in roles-based security? All you have to do is provide field from the DB that lists their role to the roles attribute of <cfloginuser>, and then wrap any code that needs to be checked in a <cfif isuserinrole("foo")> block. It's not difficult at all ... or am I missing something?
I have a RIDICULOUSLY FEATURE RICH security API that I've worked on for several months and am just finishing off... which I plan to release to the public fairly soon. It may be of interest to you.
@Rob: Nothing at all wrong with using the cflogin tags if it meets your needs. Some applications may need more control thats all but for a lot of apps its a great choice.
I've had issues in the past with cflogin. That's why I don't recommend it anymore. Yes - my apps still tend to use it, but I'm not using it for anything new.
Also - it only does roles based security. Ie, role X can do Y. It doens't have a concept of permissions, or roles and resources. Ie, Ray has Edit on resource Foo.
Venture forth to the land of Hal Helms. He's got a neat security model outlined here:
http://halhelms.com/writing...
I've used this on several sites and it allows you to have some fairly complex, yet granular security.
I've built completely locked down systems like @Sam built but it could've been implemented in any language.
The Basics:
Add tables, example below, to your db. For each user assign their access in usersitecomponents (or whatever you name it; just a link table between users and sitecomponents), or assign it by user type/group, and on each page request, ping the db to see if they have access to the requested page.
DB Schema -
:: SiteComponents [id, parentid, title, href, etc...]
:: UserSiteComponents [sitecomponentid, userid]
This is very fast since you're merely making a "select true from usersitecomponents where userid = session.userid and sitecomponentid = #someid#". I say "true" only because you don't need any real info here.
If you properly setup sitecomponents table you can even control a graphic on the home page.
Hope this makes sense and helps. Again, this is not CF specific at all. I just so happened to implement it in CF.
I've recently put into production a project that uses a custom security framework for exactly this purpose. This application is written in Mach-II so in addition to the security business objects I wrote a plugin and a filter. The way my framework works is pretty straight forward.
I have database tables for user, role, and permission. Users may have multiple roles and each role has a permission set (done using link tables). A permission is actually the name of a Mach-II event, or alternatively a custom value which is used for inserting custom validations on a form (for example to show or hide certain buttons). The events themselves get checked every request through the plugin in the preEvent() method.
In this way I can secure everything at the event level which is usually adequate, and when custom security is needed I can include calls to the security business objects on the views to test if the user is allowed to see a button or hidden panel.
Very easy to implement with Mach-II and I imagine you could do something like this in most of the popular MVC frameworks in a fairly lightweight manner.
Eric
Along the line of what Eric has done, I too have designed and implemented a custom security system using a similar idea linking users, roles, and resources for an online school. The requirements of the school's desired security system pretty much meant I had to build one from scratch.
The ultimate goal of this security system was to surround code from either being displayed or executed via a <cfif> statement with a straighforward call to a cfc function "isUserAllowed("[ResourceName]"). This function would make a database call to query whether the logged in user had access to the specific resource either via a user-->to-->resource assignment or user-->to-->role-->to-->resource assignment.
The intelligence in the system would honor the business requirements that a user would be given access if at least one assignment either via a role or direct user assignment was granted UNLESS, there was any assignment that DENIED access, thereby not giving them access to the resource.
That's the crux of the system with some more layers of intelligence that would be too detailed to explain in a comment post. I did build an administrative security interface to this system where the engineers and internal staff are the intended audience (translates to "still needs work"). However I'm quite happy that it works and more importantly, the school loves the way it works. Yay!!!
Check out Jason Dean's Security Series: http://www.12robots.com/ind...
I've learned a lot there and gotten my way of working regarding security acknowledged thru his postings.
"We are inheriting a ColdFusion application written in ColdFusion."
o_O
oh thank god. i though you were inheriting a cf app written in perl there for a minute. thanks for clearing that up for me.
Don't forget the foundation on which these security models are based. There is a function in the Application.cfc file called onRequestStart. This function is called prior to any .cfm page being loaded, so the security usually goes into that function.
For a complete list of functions available in Application.cfc, see Ray's posting at:
http://www.coldfusionjedi.c...
@Ray,
I know you've mentioned not using CFLogin in the past as well. Maybe you could share/blog about what/how you're securing your applications? Or maybe even share the issues you have (or have had) with CFLogin? (Sorry if you've already blogged about this.) I've been using CFLogin myself for simple back-end admin areas and found it to be pretty useful.
I know a number of comments have recommended using various frameworks too (Mach II, ColdSpring, etc.), is this where you've headed as well?
In regards to security, there are actually several levels, even within application security. To start out with, one should use CF's basic security framework, which includes cflogin. CFLogin includes providing a list of roles the user has. From this list, one can query whether the user has a given role using CF built in functions. This could handle the view layer issues on what to display and what to not display.
The next layer of securiy is CF's ability on the components to restrict methods by role. This allows the application to restrict certain methods/components to users assigned the higher level of access, such as administrative functions.
One layer that Ray didn't touch upon, however, is security in the database itself. Often on web-based SQL Server databases, where I do have direct access to the backend, I set up the user that CF uses to connect to the database as having at most DataReader and DataWriter roles. Within the CF Admin, I take away the ability to create or drop objects. One could even go so far as to only allow the user CF connects with to execute Stored Procedures.
One of the items I brought up at CF United on the first day during the keynote, is an area lacking in CF. This is the ability to pass the authenticated user information onto the database. Oracle has the ability to connect with a common account to allow for connection pooling of database connections, but within the connection, one can also pass the user authenticated to the middle tier (Oracle's Proxy Authentication). This allows you to establish roles based on individual user coming in, and retain auditing capabilities of actual data access (important for such things as HIPAA compliance).
A couple other points on Database Level Security. Oracle has the ability to have roles passworded (i.e., one has to activate the role via a password). The problem here with Cold Fusion is the fact that you, the programmer, are for the most part removed from the actual Java connection hassles. In this case, however, one needs to retain the connection, or in each request cycle turn on the role, since there is no guarantee that the role will be activated when the requests starts. This is really more a client-server based model that should be discouraged for multi-tiered database interactions. Oracle's Proxy Authentication is a better approach in this case.
One final security related issue that I am not sure if it has been fixed or not, since I haven't played around with CF8 enough, is the fact that transactions run as the CF account you set up in CF datasource setting. One could provide username and password for individual queriess, but for Transactions, it ran as the default user account.
The problem with securing things at the Controller level (i.e. Model-Glue events) is that AJAX and especially Flex applications don't talk to the Controller much, if at all. Which means security often needs to be applied at the Model layer. This is where something like ColdSpring's AOP capabilities can be very useful. It also needs to be robust enough to handle more complex authorization, such as "a user can edit a News item, but only if they created it" to avoid people modifying the URL/web service/AMF request and trying to access data that isn't theirs. It can become a pretty interesting problem depending on how complex the rules get.
Resinfox access control for model-glue - http://resinfox.com/num/mod...
This has been on my list of things to check out forever.
Not sure if it's possible to work model-glue around/into the existing app though.
C
@SteveW: If you search my blog for cflogin you will see my history of woe with with it...