First of all, I think this is a bad idea; because, it fosters the illusion that you don't have to protect the individual functions - you DO have to protect them. Methods of forcing users to navigate in a particular fashion are not foolproof. Nevertheless, the customer ... is the customer. So, how do you give this request the attention it deserves?
It's based on the premise that when a browser moves from one page to the next through a link or through the action attribute of a form, the URL of the page the browser just left is available as HTTP_REFERER. (Yes, I know referrer is spelled wrong, but blame it on the folks who created the standard and use their spelling. It's not ColdFusion's fault, either.)
Create a "work1" directory just below the root and put this code in Application.cfm within it. Once you've done this, anyone simply pasting a URL into the browser will eventually be diverted to the menu.
<cfif not len(trim(cgi.http_referer))> You have strayed. "Return" will bring you back to the menu. <form action="../menu.cfm"><input type="submit" value="Return"></form> <cfabort> </cfif>
Suppose, however, that I have my own Web site and I'm tired of your lousy navigation scheme. If I create a page on my own site that links to where I want to go, http_referer will have a value: MY domain name and directory down to the page I came from. Knowing this also helps you plan a defense that can still be generic but a bit stronger. Create a "work2" directory just below the root and put this code in Application.cfm there.
<cfif cgi.http_referer does not contain cgi.server_name> You have strayed. "Return" will bring you back to the menu. <form action="../menu.cfm"><input type="submit" value="Return"></form> <cfabort> </cfif>
Build a very simple menu, menu.cfm, at the root.
<a href="work1/function1.cfm">Function 1</a> <p> <a href="work2/function2.cfm">Function 2</a>
Build function1.cfm in work and function2.cfm in work and work2 respectively. Have them say "You have reached the page for function 1" and "You have reached the page for function 2" respectively.
Now from some other site - maybe you have a cheap site that doesn't have ColdFusion - make a page and link to function 1. This time, you'll reach function 1 without going through the menu. The protecting code only checks to be sure you didn't paste in a URL; it doesn't care what it is.
Try to reach function 2 from some other site. Make a page link from there to function 2. Notice that this time you're blocked; because, the refering page isn't in the same domain as the target link, and the code does care.
Finally, you could also be attacked from text fields on your own Web site - similar things have been done in an attempt to use your own domain name against you. In the final analysis, checking the referring page will keep all but the most determined people away from your resources, but determined people are the ones you bring out the big guns for.
<cflocation url="../menu.cfm"> <cfabort>
Build function3.cfm in work3. Have it say: "You have reached the page for function 3".
Try to browse that page from anywhere; you can't, not even with a link or as a form action. So what good is it? You can INCLUDE it whenever appropriate. However, browsing it will cause Application.cfm to be included first, causing the diversion.