Wednesday, May 13, 2009

Active Directory Users CFC

Pull user info out of Active Directory for Flex

So I have been working on a project for creating a Company Directory in Flex and wanted to pull the data about employees out of Microsoft's Active Directory.  I chose AD because this seems to be the most up to date info about employees and their status as employees. Some employee databases don't get updated right away when someone get hired/fired, but AD sure does due to it's security model on the network.  People need to login on their first day, and Managers want them locked out on their last.

Upon doing some research a few years ago on this subject I saw that ColdFusion had an LDAP tag built-in and could query AD relatively easily.  I decided to once again go this route and create a CFC that would query Active Directory, and Flex could just call using Remote Object.

Some of the challenges with using AD is that I wanted it to be easy for Admins to populate AD the way they've always done it and feel most comfortable.  This means using the Active Directory Users and Computers dialog forms within Windows.  The problem here is that not every field I wanted, even though it may be in Active Directory, is available within the dialog forms.  Some of the workarounds I came up with was to populate the un-used fields that already exist in the dialog but use them for other purposes.  For example on the General tab there is a field called "Web Page"...so no one at this company has their own webpage,and this is usually just left blank.  I decided to put the employee photo filename here, and have Flex work it out to pull the image directly from the server using this information.  Also, DOB is not included in any of the forms, so I had to add this to the Notes field and preceed it with "DOB:" and let Flex parse it out and convert it to a date.

Despite the shortcomings of Microsoft, this CFC and Flex does a really good job at getting this info and it's really fast!  I think the ultimate in customization would be to have a Flex Users admin screen where we can just populate AD directly and add in any custom fields we want into AD, including a raw ByteArray field for images.

<cfcomponent extends="Service">
   
<cffunction name="getEmployees" access="remote" returntype="query">
<!---This function will bomb in Flex if the defaults below are not set properly--->

<!---************CHANGE DEFUALTS BELOW**************--->
<!---Replace with your Domian name--->
<cfparam name="domain" default="YOUR_DOMAIN">
<!---Replace with your Domian Controller name--->
<cfparam name="server" default="YOUR_ACTIVE_DIRECTORY_SERVER_NAME">
<!---Replace with an Administrative AD account--->
<cfparam name="username" default="Administrator">
<!---Replace with account password --->
<cfparam name="password" default="ADMINPASSWORD">
<!---Replace with your specific LDAP port number if different from MS default--->
<cfparam name="port" default="389">
<!---************END OF DEFAULTS***See Below for more options--->

<!---OK, Ready?...Try to get employee data from Active Directory--->
<cftry>
<cfldap action="QUERY"
    name="ldapquery"
<!--- Most popular fields pulled from AD Users you can add more if you wish. View AD schema with any LDAP viewer --->
    attributes="sn,givenname,initials,title,department,company,ipPhone,telephoneNumber,mail,physicalDeliveryOfficeName,wwwhomepage"
<!---Look in Users containter only, Bitch--->
    start="cn=users,dc=#domain#"
<!---Used to filter AD...looks at "Office" field in AD Users (physicalDeliveryOfficeName) and pulls record if populated with "DCC"  Change as nessesary.  userAccountControl makes sure to only select users who are NOT(!) disabled in AD.  Looks crazy, but we're talking Microsoft here--->
    filter="(&(objectclass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)) (physicalDeliveryOfficeName=DCC))"
    sort="givenname"  <!--- Sort records by First Name.  Change fields as nessesary or comment out for "random" results--->
     server="#sever#.#domain#"
    port="#port#"
    username="#domain#/#username#"  
    password="#password#">                 

        <cfcatch type="any"> <!---If LDAP query fails for any reason...execute this and return 0 records.--->
            <cfset UserSearch = "Failed">
            <cfset ldapquery.RecordCount = 0>
        </cfcatch>
</cftry>
    
    <cfreturn ldapquery>  <!---Return data back to Actionscript--->

</cffunction>    
</cfcomponent>

-Christopher C. Keeler

No comments:

Post a Comment