Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with:

Ask Ben: Blocking WSDL Access In A ColdFusion Application

By Ben Nadel on

Is there any way to hide the WSDL file generated from a CFC from being viewed on a browser? Evidently .NET allows you to modify the web.config to make this happen; was looking for an equivalent in CF. Thanks much.

First off, I have to say that I have no idea why you would want to do this, and I have to say I'm very curious. Perhaps you are trying to discourage SOAP-based access to a given component? Curiosity aside, however, there are a number of ways you could do this; if you want to stay outside of the ColdFusion application logic, you could create a URL rewriting rule that checks for the WSDL flag and blocks the request. But for my money, I like to keep things in-application as much as possible. As such, I'll show you how to use the ColdFusion application framework to block WSDL file access.

WSDL files (Web Services Description Language) are not web accessible in a ColdFusion application; they are automatically generated by the ColdFusion server and cached somewhere within the installation directory. To access a WSDL file, you must append the "WSDL" URL parameter to the location of the target component:

MyComponent.cfc?wsdl

At this point, ColdFusion will automatically retreive the cached WSDL file and serve it up as the XML response. While it does this automatically, it still obeys the rules of the ColdFusion application in which the request was made. As such, if we want to prevent the server from serving up the WSDL file, we simply have to tell the ColdFusion server not to process the request. Luckily, the ColdFusion application framework (Application.cfc) provides us with the onRequestStart() event handler which is exactly where this kind of request management should take place.

Application.cfc

  • <cfcomponent
  • output="false"
  • hint="I define the event settings and event handlers.">
  •  
  • <!--- Define the application settings. --->
  • <cfset this.name = hash( getCurrentTemplatePath() ) />
  • <cfset this.applicationTimeout = createTimeSpan( 0, 0, 5, 0 ) />
  •  
  • <!--- Define the request settings. --->
  • <cfsetting
  • requesttimeout="10"
  • showdebugoutput="false"
  • />
  •  
  •  
  • <cffunction
  • name="onRequestStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="I initialize the request.">
  •  
  • <!---
  • Check to see if the WSDL flag is present in the URL.
  • If so, we can block it as we initialize the request.
  • --->
  • <cfif structKeyExists( url, "wsdl" )>
  •  
  • <!---
  • Set the header so that the client understands
  • that the WSDL file was purposefuly denied. This
  • part is not required, but it will provide less
  • confusion if the end-user "believes" there should
  • be a WSDL file available.
  • --->
  • <cfheader
  • statuscode="403"
  • statustext="Forbidden"
  • />
  •  
  • <!---
  • Return False - this will prevent the rest of the
  • page from processing (ie. the requested template
  • will not execute).
  • --->
  • <cfreturn false />
  •  
  • </cfif>
  •  
  • <!--- Return true to let page request process. --->
  • <cfreturn true />
  • </cffunction>
  •  
  • </cfcomponent>

The onRequestStart() event handler is the part of the ColdFusion application framework that allows us to manage all points of access to our application. By returning True or False from this event handler, we either grant or deny the processing of the current request respectively. As you can see in the above code, if the WSDL flag is present in the URL, our onRequestStart() event handler returns false. This effectively blocks the page from being processed.

Returning False from onRequestStart() simply prevents the rest of the request from being processed; it doesn't change anything else. As such, returning False still generates a "200 OK" status code response to the client. If a client is expecting a WSDL file to be there, this 200 response can be quite confusing. That's why, in the above code, we are explicitly setting a "403 Forbidden" response. This way, the client sees that the WSDL file has been explicitly blocked by the application, which will hopefully be less confusing.

To test this, I set up a page that performs a CFHTTP request to a WSDL file in the above application:

  • <!--- Define the URL of the WSDL file. --->
  • <cfset wsdlURL = (
  • "http://" &
  • cgi.server_name &
  • getDirectoryFromPath( cgi.script_name ) &
  • "Test.cfc?wsdl"
  • ) />
  •  
  • <!--- Attempt to get the WSDL file. --->
  • <cfhttp
  • result="get"
  • method="get"
  • url="#wsdlUrl#"
  • />
  •  
  • <!--- Output the WSDL request response. --->
  • <cfdump
  • var="#get#"
  • label="CFHTTP WSDL Response"
  • />

When we run this code, we get the following CFDump output:

 
 
 
 
 
 
Blocking WSDL File Access In A ColdFusion Application Using The ColdFusion Application Framework. 
 
 
 

As you can see, the request comes back with a "403 Forbidden" response and an empty file content.

Like I said at the beginning, I am not sure why one would want to block WSDL file access; but, that said, I hope that this was helpful!



Reader Comments

Great solution and use of onRequestStart(). I agree, a straight block of the wsdl appears to contradict the purpose of developing a SOAP based web service interface (because it would also block the client.) However, if there was a way to extend your code to allow certain s/w clients in and the rest of the browser world out, I think that would be useful. It would make your components and methods less visible to the public.

Reply to this Comment

@Larry,

You can still make SOAP requests without a WSDL file; the WSDL file is only a sort of documentation. When you make the actual SOAP post, the WSDL file is not used. As such, you could theoretically use this approach to block people from the documentation - only allow those who already *know* how to call your SOAP requests.

Reply to this Comment

If you make a web service SOAP call from Flex, it needs the WSDL file to figure out which methods are available and what parameters are needed. So, with Flex it downloads the WDSL file first from the server then it makes the SOAP method request.

Reply to this Comment

@Larry,

I know next to *nothing* about FLEX, but that might only be true if you are using RemoteObjects? If you use a straight-up HTTP request, then it should probably be able to due it. Of course, at that point, you have to manually parse the XML that gets returned. The beauty of SOAP "wrappers" is that they take care of all the data conversion for you (most of the time).

Reply to this Comment

Unfortunately it's required if using SOAP web services via Flex app. Here is a Flex snippet:

// this sets and downloads the wsdl doc from server
ws.wsdl = "http://www.xxxxx.com/ws/comp.cfc?wsdl";
ws.loadWSDL();

// event listener setup
ws.methodName.addEventListener(ResultEvent.RESULT,onResult);
ws.methodName.addEventListener(FaultEvent.FAULT, onFault);

// make the method request
// this makes the request to the server based on
// api described in the wdl file
ws.methodName.send(para1,para2);

Reply to this Comment

@Larry,

Right, but you're still using a "wrapper" at that point. What I meant was that if you use something like "HTTPService", where (as with CFHTTP) you have to code it manually, it would work.

Of course, that's just for sake of argument. In reality, I am sure that would be a SUPER pain in the butt :)

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.