ColdFusion Muse

Server-side Vs. Client-side Validation Revisited

CF Muse Reader Asks:
You suggest both client and server side should be used for validation. Just to check - I should code so that js picks up the errors first using event code or onsubmit then let server side pick up the errors on submit using cfinput validate/required etc. Or do I recode all the stuff to be event driven such as onchange etc.

This question refers to the previous post on form validation. From the way the question is phrased I believe the reader is probably proficient at JavaScript. There are some amazing things you can do with JavaScript, and I'm in favor of creating intuitive interfaces that help your user cope with the complexity of your application. Obviously JavaScript is or can be a big part of that solution. If your concern is to provide a better user experience then JavaScript is helpful and necessary. If your concern is to validate your data for accuracy and security then you must use server side code to check your form inputs.

As an example, you might have a form like this:

<form action="myForm.cfm" method="post" onsubmit="validate()">
   <input name="myName" type="text">
   <input name="myDateOfBirth" type="text">   
   </form>
Let's say JS function "validate()" checked to make sure "myDateOfBirth" was actually a date and was in the last 120 years before submitting. That would be useful for the user if he happened to type in 1/12/198 instead of 1/12/1982. If, however, JS is turned off he may be able to submit the form anyway - regardless of the input. More importantly, if this is an important form and the user is up to no good, he can simply re-create your form on his own web site and point it to your domain - firing post requests willy nilly till he sees a hole. In fact, let's say the form above was in a folder called "forms" on "mydomain.com". This snippet of code would allow him to circumvent your clever JavaScript with no problem.

<cfhttp url="http://mydomain.com/forms/myform.cfm" method="post">
      <cfhttpparam type="FORMFIELD" name="myName" value="Attila The Hun"/>
      <cfhttpparam type="FORMFIELD" name="myDateOfBirth" value="02/05/406"/>
   </cfhttp>

Server Side Comes First

The point is, that regardless of what you do on the client you should validate the inputs on the server. On a public form you have little or no control over what is happening on the client. All you can really control is what goes into you application or database.

Now, the second part of the question asks about "cfinput" and "validate/required". To be clear, when you use CFFORM you are not creating server side code. You are, in fact creating complex JavaScript routines for validation that function on the client side - so you are not using server side validation. On a side note, I really detest cfform and tend to avoid it in favor or custom JS or something like Dan Switzer's "Qforms". Unless I'm using flash forms I avoid cfform altogether. One additional approach provided by Coldfusion that some folks use is the "hidden variable" approach. The muse reader above may be referring to this idea. It's actually a rudimentary method for server side validation. Here's how it works. You would alter your form as follows:

<form action="myForm.cfm" method="post" onsubmit="validate()">
   <input name="myName" type="text">
   <input name="myName_required" type="hidden" value="You must provide a name">
   <input name="myDateOfBirth" type="text">   
   <input name="myDateOfBirth_date" type="hidden" value="You must provide a valid date">
   </form>

Cleverly, Coldfusion looks for the "_required" or "_date" (or _integer or _float etc. - see the docs) that matches the name of a form element and then validates that element on the server - displaying the message you have chosen to the user and asking them to go back and fix the problem. Yes, this is server side validation because the server is doing the checking, but is it secure from malicious attack? Nope. All a nere-do-well has to do is remove the "myDateOfBirth_date" form element from his custom form or CFHTTP call. The server's validation is based on these inputs being present. If those form elements are not part of the request, the server will not check them.

What is Server Side

Server side validation is the process of painstakingly checking the inputs and making sure they contain what they are supposed to contain. Most of my server side validation code looks like this:

<cfscript>
   
// default values
   
err   =   0;
   msg   =   '';
   
// check for name (isEmpty checks "trim(len(arg))"
   
if(isEmpty(form.myName)) {
      err      =   1;
      msg      =   '<p>You must provide a name</p>';
   }
   
// check for date
   
if(isEmpty(form.myDateOfBirth)
      OR NOT isDate(form.myDateOfBirth)
         OR dateDiff('yyyy',form.myDateOfBirth,now()) GT 120) {
      err      =   1;
      msg      =   '<p>You must provide your date of birth
                  and you must be living</p>';
   }
   
// if not err pass the args
   
if(NOT err)
      msg      =   resourceCfc.addUser(argumentcollection=duplicate(form));
   
</cfscript>
As you can see I've taken the time to specify individual form elements and conditions in my handler.

In my opinion, if security and data integrity are your primary concerns, you should start with server side validation and put it above client side validation in importance. You should add client side validation to reduce round trips to the server and maximize the user experience but don't rely on it to keep your site safe or your data sound.

Comments
Dan G. Switzer, II's Gravatar In every presentation I've ever done about client-side validation, I've always made the point that server-side validation is the most important aspect.

Client-side validation basically just improves the UI for the user. I'm a strong advocate of client-side validation, but I've also seen people spend to much time trying to bullet proof their client-side validation while ignoring server-side validation.

Client-side validation should be designed to catch user mistakes and notify them of the mistakes quickly. Server-side validation ensures that the values receive constrain to your business logic rules and that they don't break your code.
# Posted By Dan G. Switzer, II | 3/16/06 8:41 AM
Craig M. Rosenblum's Gravatar I agree with you there..

It's like the story of the fireman, who has pants and suspenders, sure the suspenders are nice, but if they fall and you have no belt, how will you hold your pants up?

So use client validation, it's great as a first step for validation..But have the server side just in case, especially if you use it within queries or any other highly sensitive to hackers.

<cfqueryparam
<cfparam

all ways to specify datatype's for incoming variables.

Even if your not using it in a query, what if the data isn't the datatype you expect and they had javascript off?

cfif isdefined(form.my_variable)

sure the above prevents if the variable does not exist

but what if you need a numeric value and you get a string garbage as well.

Good post, mark.
# Posted By Craig M. Rosenblum | 3/16/06 8:45 AM
mkruger's Gravatar Dan - Craig - thanks for the comments - I can feel the love :)
# Posted By mkruger | 3/16/06 9:22 AM
Ryan Guill's Gravatar While this is somewhat off topic and a whole different paradigm, it is worth noting that using flex, we will be able to rely more on client side validation, because first, there will be no way to turn it off unless they just dont use the form at all, and secondly, you are able to easily created very complex validation routines, similar to what we can do with cf on the server side, in actionscript on the client before it is sent to the server for proccessing. You may still need to do some basic checking on the server side, but it wont be as much of a problem as it is with html and javascript.
# Posted By Ryan Guill | 3/16/06 9:31 AM
mkruger's Gravatar Craig, While flex does make it more difficult to hack, it still generates client side values that are ported to the server. Using something like "service capture" by Kevin Langdon (http://www.kevinlangdon.com/servicecapture) you can upack web service and AMA calls pretty handilly. Doing it all on the client side in flex only amounts to security by obscurity. It's better than pure JS, but it still has a fatal flaw.
# Posted By mkruger | 3/16/06 9:39 AM
mkruger's Gravatar Sorry.. I should have addressed that to Ryan.
# Posted By mkruger | 3/16/06 9:40 AM
Ryan Guill's Gravatar Webservice calls, yes, but I dont think this will be a problem with the coldfusion adapter. The way I understand it, it will be all binary data going back and forth. I would be very surprised to see someone be able to hack that. Now, if you are just using a flex swf to do an http post to a page, yes, the same issues reside, but using the cfadapter (mystic) I dont think you are going to have that problem. I would be interested in finding this out for sure though.
# Posted By Ryan Guill | 3/16/06 9:43 AM
Craig M. Rosenblum's Gravatar It's okay, Mark. We're all human, we make mistakes...:)
# Posted By Craig M. Rosenblum | 3/16/06 2:58 PM
mkruger's Gravatar The Coldfusion adapter uses AMA - flash remoting. This is an open binary format. The tool I mentioned by kevin langdon unpacks it for you and gives you the send params and the received data in a visible and readible format :)

Remeber too that a cfc that is enabled for remoting (meaning access="remote") is capable of receiving web service calls as well as AMA calls.... so armed with the URL you would be able to generate the WSDL, create a stub/proxy class and utilize it as a web service.

That sounds like a lot of work, but even novice developers armed with user friendly development tools that abstract the process of unpacking the XML could probably make short work of it.

Yes it IS more work than simple HTML forms, and hence "more secure" because it's "more difficult" in the same way that a $500 pound home safe is "more secure" than a $100 dollar home safe. Both, however, are still Home safes - and they don't do much good if the thief can simply abscond with them and pick them at leisure.

My point is that no matter what you choose to do on the client (and all these ideas are marvelous) you still need server-side validation.
# Posted By mkruger | 3/17/06 3:26 PM
Harel's Gravatar The Server side validation in CF is just rubbish. There is no apparent way to turn it off (please englighten me if i'm wrong).
In fact, its been like this forever, and I'm sure people requested one of the many CF 'owner' companies to fix this and at the very least allow this stupid auto validation to be turned off. But why would the listen - some issues are best kept for the next 'owner of the platform' to deal with. It has caused me a great deal of headache as I"ve had to work around this many times.
(don't tell me to rename my fields as this is not always possible. A field titled "request" and one "request_date" are logical fields to be present in a database/form/app.)
# Posted By Harel | 6/23/06 6:23 AM
mkruger's Gravatar Harel,

I agree about the server side validation - and I don't know anyone who uses it. I would never used "canned" validation for anything important anyway. I made that very point above.

As for "turning it off" so you can use your pet naming convention... why would you NOT be able to rename a form field? My only conclusion is that you are using "cfupdate" or "cfinsert" to get your data into your database. that is also a bad idea. Write SQL insert statements instead. Cfupdate is too restrictive and gives you very little feedback on what's going on under the covers. And you can't leverage SQL either - as in a combined insert/update statement.

That's my take - so I agree with you half way ... is that good enough for us to remain friends? :)
# Posted By mkruger | 6/23/06 7:54 AM
Harel's Gravatar Man,
If you assume I'd use a useless tag like cfinsert/cfupdate then we won't BE able to be friends in the first place ;o)

The application i'm working on is most likely the largest CF application in the history of this (silly) platform. I can't disclose the details though I can say it is used by many government authorities in the UK and by that definition - that makes it huge in the sense of the biz logic and strictness it uses. It's bolted on an old (over 10 years) oracle db whose columns cannot be changed.

The app is built on a framework I created which kinda resembles hibernate but on steroids. Think 'automatic gui generation with total db persistency'. The amount of forms this app generates is HUGE. Renaming db fields is out of the question. The framework is solid, and runs many apps within it as modules. Infact, I wish I could release it somehow (I can't obviously).

We worked around that problem though the very existence of this kind of silly issue adds additional nails to the coffin of CF.

I can't help but wonder - if the next CF owner is Microsoft - would it be renamed ColdFusion MS?

(i was kidding of course - we can remain friends - just don't mention cfinsert/update ever again ;o)
# Posted By Harel | 6/23/06 12:23 PM



Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.