Ask Ben: Blocking WSDL Access In A ColdFusion Application

Posted March 17, 2010 at 8:56 AM by Ben Nadel

Tags: ColdFusion, Ask Ben

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

Mar 17, 2010 at 12:17 PM // reply »
5 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.


Mar 17, 2010 at 12:33 PM // reply »
15 Comments

I could see where this might come in handy to help lock down a remote proxy.


Mar 17, 2010 at 1:35 PM // reply »
11,246 Comments

@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.


Mar 17, 2010 at 1:53 PM // reply »
5 Comments

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.


Mar 17, 2010 at 2:03 PM // reply »
11,246 Comments

@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).


Mar 17, 2010 at 2:27 PM // reply »
5 Comments

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);


Mar 17, 2010 at 2:31 PM // reply »
11,246 Comments

@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 :)


Mar 17, 2010 at 2:43 PM // reply »
5 Comments

You are correct. You can use HTTPservice RPC model instead and not worry about the wrapper. Not too much harder to do but not as extensible or fun!

I wonder if the Flex app could pass an arg after the wsdl and then have onRequestStart filter based on that?

ws.wsdl = "http://www.xxxxx.com/ws/comp.cfc?wsdl&x=letmethru";


Mar 17, 2010 at 2:52 PM // reply »
15 Comments

<cfif structKeyExists( url, "wsdl" ) and not structKeyExists( url, "x")> should fix that


Mar 18, 2010 at 9:16 AM // reply »
5 Comments

Ben, Robert great stuff that I can use. Thanks.


Mar 22, 2010 at 8:14 PM // reply »
11,246 Comments

@Robert,

Thanks for jumping in on that one. @Larry, that should be exactly what you need.


Mar 23, 2010 at 8:35 AM // reply »
15 Comments

@Ben

No worries. Happy to help.


Post A Comment

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.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 24, 2013 at 11:21 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, Ha ha, let's us never speak of justifying "##" notation again :P ... read »
May 24, 2013 at 11:18 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Ah, so it was indeed how I vaguely remembered it to be: A direct assignment value = users.id[ i ] causes value to retain the sticky datatype of the query column. Although unnecessary in ... read »
May 24, 2013 at 9:11 AM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Brandon, Hi, No, I haven't been able to do that. I have just kept it as it is. ... read »
May 23, 2013 at 9:52 PM
Preventing Links In Standalone iPhone Applications From Opening In Mobile Safari
@Muhmmadibn Did you figure out a solution to launching PDFs? I am running into the same issues myself. There is no way to close the PDF or go back once you launch it. Thanks in advance! ... read »
May 23, 2013 at 6:06 PM
The Girl Who Broke My Heart, And Made Me A Better Person
Good day,ladies and gentle men, my name is Dr AMADI the great spell caster in Africa, i have help so many people for different kind of problems,who say there is no solution to problems on earth, that ... read »
May 23, 2013 at 4:26 PM
ColdFusion QueryAppend( qOne, qTwo )
@Heather, Glad people are still getting value out of this! ... read »
May 23, 2013 at 3:49 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@WebManWalking, I meant the code at the bottom (not the video). I did try to experiment with an intermediary variable, like: value = users.id[ i ]; arrayContains( userIDs, value ); ... but t ... read »
May 23, 2013 at 11:06 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben, Are you talking about As Number: YES As String: YES As Java: YES? If so, that's with 3 different ways of referencing the constant 1, not users.id[1]. Query object references(*) are what seem ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools