views:

766

answers:

4

Is there a recommended (and preferably free) way in ColdFusion to access a remote file that is protected by NTLM authentication? The cfhttp tag appears to only support Basic authentication.

+4  A: 

This CFX Tag - CFX_HTTP5 - should do what you need. It does cost $50, but perhaps it's worth the cost? Seems like a small price to pay.

Adam Tuttle
+1 It's how I did it once. Works good!
Jas Panesar
This isn't a bad solution; I've used it in the past and it works. What I'd like to avoid isn't so much the monetary cost, but the hassle cost of maintaining licenses and an external dependency.
Soldarnal
Well, you currently can't do it natively in CF, so either you need a third-party solution like this or need to roll your own.
Al Everett
There are also free java libraries that will do similar things, but none of them will be as easy to use as the CFX tag.
Adam Tuttle
+1  A: 

Here is some code I found in:

http://www.bpurcell.org/downloads/presentations/securing_cfapps_examples.zip

There are also examples for ldap, webservices, and more.. I'll paste 2 files here so you can have an idea, code looks like it should still work.

<cfapplication name="example2" sessionmanagement="Yes" loginStorage="Session">
<!-- Application.cfm -->
<!-- CFMX will check for authentication with each page request. -->
<cfset Request.myDomain="allaire">

<cfif isdefined("url.logout")>
    <CFLOGOUT>
</cfif>


<cflogin>
   <cfif not IsDefined("cflogin")>
      <cfinclude template="loginform.cfm">
      <cfabort>
   <cfelse>
      <!--Invoke NTSecurity CFC -->
     <cfinvoke component = "NTSecurity" method = "authenticateAndGetGroups"
      returnVariable = "userRoles" domain = "#Request.myDomain#"
      userid = "#cflogin.name#" passwd = "#cflogin.password#">
     <cfif userRoles NEQ "">
      <cfloginuser name = "#cflogin.name#" password = "#cflogin.password#" roles="#stripSpacesfromList(userRoles)#">
      <cfset session.displayroles=stripSpacesfromList(userRoles)><!--- for displaying roles only --->
     <cfelse>
      <cfset loginmessage="Invalid Login">
      <cfinclude template="loginform.cfm">
      <cfabort>
     </cfif>
   </cfif>
</cflogin>

<!-- strips leading & trailing spaces from the list of roles that was returned -->
<cffunction name="stripSpacesfromList">
    <cfargument name="myList">
    <cfset myArray=listtoarray(arguments.myList)>
    <cfloop index="i" from="1" to="#arraylen(myArray)#" step="1">
     <!--- <cfset myArray[i]=replace(trim(myArray[i]), " ", "_")> 
     out<br>--->
     <cfset myArray[i]=trim(myArray[i])>
    </cfloop>
    <cfset newList=arrayToList(myArray)>
    <cfreturn newList>
</cffunction>

This is the cfc that might be of interest to you:

<!--- 
This component implements methods for use for NT Authentication and Authorization.

$Log: NTSecurity.cfc,v $
Revision 1.1  2002/03/08 22:40:41  jking
Revision 1.2  2002/06/26 22:46  Brandon Purcell
component for authentication and authorization
--->

<cfcomponent name="NTSecurity" >

        <!---  Authenticates the user and outputs true on success and false on failure. --->
        <cffunction name="authenticateUser" access="REMOTE" output="no" static="yes" hint="Authenticates the user." returntype="boolean">
                <cfargument name="userid" type="string" required="true" />
                <cfargument name="passwd" type="string" required="true" />
                <cfargument name="domain" type="string" required="true" />
                <cftry> 
                        <cfscript>
                        ntauth = createObject("java", "jrun.security.NTAuth");
                        ntauth.init(arguments.domain);
                        // authenticateUser throws an exception if it fails, 
                        ntauth.authenticateUser(arguments.userid, arguments.passwd);
                        </cfscript>

                <cfreturn true>
                <cfcatch>
                <cfreturn false>
                </cfcatch>
                </cftry>  
        </cffunction>

        <!--- 
                Authenticates the user and outputs true on success and false on failure.
        --->
        <cffunction access="remote" name="getUserGroups" output="false" returntype="string" hint="Gets user groups." static="yes">
                <cfargument name="userid" type="string" required="true" />
                <cfargument name="domain" type="string" required="true" />

                 <cftry>
                        <cfscript>
                        ntauth = createObject("java", "jrun.security.NTAuth");
                        ntauth.init(arguments.domain);
                        groups = ntauth.GetUserGroups(arguments.userid); 
                        // note that groups is a java.util.list, which should be 
                        // equiv to a CF array, but it's not right now???
                        groups = trim(groups.toString());
                        groups = mid(groups,2,len(groups)-2);
                        </cfscript>
                       <cfreturn groups>
                <cfcatch>
         <cflog text="Error in ntsecurity.cfc method getUserGroups - Error: #cfcatch.message#" type="Error" log="authentication" file="authentication" thread="yes" date="yes" time="yes" application="no"> 
                        <cfreturn "">
           </cfcatch>
                </cftry>  

        </cffunction>

        <!--- 
                This method combines the functionality of authenticateUser and getUserGroups. 
        --->
        <cffunction access="remote" name="authenticateAndGetGroups" output="false" returntype="string" hint="Authenticates the user and gets user groups if it returns nothing the user is not authticated" static="yes">
                <cfargument name="userid" type="string" required="true" />
                <cfargument name="passwd" type="string" required="true" />
                <cfargument name="domain" type="string" required="true" />  
                 <cftry>  
                        <cfscript>
                        ntauth = createObject("java", "jrun.security.NTAuth");
                        ntauth.init(arguments.domain);
                        // authenticateUser throws an exception if it fails, 
                        // so we don't have anything specific here
                        ntauth.authenticateUser(arguments.userid, arguments.passwd);
                        groups = ntauth.GetUserGroups(arguments.userid);

                        // note that groups is a java.util.list, which should be 
                        // equiv to a CF array, but it's not right now
                        groups = trim(groups.toString());
                        groups = mid(groups,2,len(groups)-2);
                        </cfscript>     
                <cfreturn groups>
                <cfcatch>
                        <cfreturn "">
           </cfcatch>
                </cftry>   

        </cffunction>

</cfcomponent>
Jas Panesar
This seems more for if I want to secure my own application with NTLM. Or am I understanding this wrong?
Soldarnal
Sorry, I misread the question!
Jas Panesar
A: 

You could try following the guidance here: http://cfsilence.com/blog/client/index.cfm/2008/3/17/ColdFusionSharepoint-Integration--Part-1--Authenticating

Here is what it boils down to you doing:

edit the client-config.wsdd

Change

<transport 
    name="http" 
    pivot="java:org.apache.axis.transport.http.HTTPSender">
</transport>

to

<transport 
    name="http" 
    pivot="java:org.apache.axis.transport.http.CommonsHTTPSender">
</transport>
Goyuix
Hmm, this looked promising, but didn't work for me. Maybe CF only uses Axis when making a SOAP request? (I'm just trying to grab a plain text file.)
Soldarnal
A: 

if the code from Brandon Purcell that uses the jrun.security.NTauth class doesnt work for you in cf9 (it idnt for me) the fix was to use coldfusion.security.NTAuthentication class instead. everything worked fine

Jon Briccetti