- Getting Started
- Exercise 1: The Database, "myFlashComDb.mdb"
- Exercise 2: The ColdFusion Component, "FCS_Security.cfc"
- Exercise 3: The Flash Movie, "FCS_Secure.fla"
- Exercise 4: The Server-Side ActionScript, "main.asc"
- Testing the Application, Some Considerations
Exercise 2: The ColdFusion Component, "FCS_Security.cfc"
In this exercise you construct the ColdFusion service methods used by both the Flash Communication Server and Flash Player 6. You will build these service methods inside a ColdFusion Component (not to be confused with the Flash UI Componentsthey are completely different). These service methods connect with the database you built in Exercise 1. There are three principle methods (or CFFUNCTION objects) required for this project; however, a fourth function is included to help you grow this application.
Create a new file in Dreamweaver MX, or your favourite ColdFusion IDE called "FCS_Security.cfc", and place it within the folder flashcom/applications/informIT. Make sure this folder is mapped from the default web server. (This will be the same web server that you use to access the ColdFusion Administrator.)
Add the following CFCOMPONENT tags to the file. The methods following will be placed within these tags:
<cfcomponent> <!--- place the cffunction definitions between these tags ---> </cfcomponent>
Method #1: authenticateUser
The authenticateUser function is used by Flash MX to make the initial login/password challenge to the database. It requires two parameters, login and password. This function returns an object to Flash, so the object (ret_obj) is setup, as a ColdFusion structure.
Initial keys (or properties) are set, and then the database query is challenged. This will determine if the login and password matched a record in the database. If a match was found, the function "setTicket" is called to generate a ticket.
The setTicket function is defined after this one. It returns a ColdFusion structure with two keys, TICKET and EXPIRY. When received, these keys are copied into the ret_Obj object that is returned to the Flash Player. Figure 5 shows the complete structure of ret_Obj returned by the authenticateUser function.
<cffunction name="authenticateUser" access="remote" returntype="any"> <cfargument name="login" type="string" required="yes"> <cfargument name="password" type="string" required="yes"> <!--- Challange the Login / Password sent from the Flash Player ---> <CFQUERY NAME="q_checkUser" Datasource="myFlashComDb.mdb"> SELECT UserID, fname, lname From Users WHERE login = '#arguments.login#' AND Password = '#arguments.password#'; </CFQUERY> <CFSCRIPT> // Setup return object structure, and set the initial values of the keys ret_Obj = structNew(); ret_Obj.isLoginOK= false; ret_Obj.userName = q_checkUser.fname & " " & q_checkUser.lname; // Check if the Login & Password received, matched a record in the Db if (q_checkUser.recordCount neq 0) { // call the cf function, "setTicket" passing it the UserID ticketObj = this.setTicket(q_checkUser.UserID); // Copy the ticket object into the local ret_obj scope ret_Obj.ticket = ticketObj.ticket; ret_Obj.expiry = ticketObj.expiry; ret_Obj.isLoginOK= true; } // RETURN the structure. The Flash Remoting Gateway will convert this structure // into a valid ActionScript object. //The structure's keys will become object properties return ret_Obj; </CFSCRIPT> </cffunction>
Figure 5 The ColdFusion Structure returned by the authenticateUser method is assembled automatically by Flash Remoting MX into an ActionScript Object with four properties.
Method #2: setTicket
The setTicket method is not directly called by either the Flash Communication Server or the Flash Player. It is intended to be called by the authenticateUser() method. Its role is to simply generate a ticket and the expiry date. It also stores these values in a separate table in the database. This storage bridges the gap between the Flash Player and Flash Communication Server.
The internal ColdFusion function CreateUUID() will generate a unique value. The Universally Unique IDentifier (UUID) is a 35-character string representation of a unique 128-bit integer. ColdFusion uses the unique time-of-day value, the IEEE 802 Host ID, and a cryptographically strong random number generator to generate UUIDs. It conforms to the principles laid out in the draft IEEE RFC "UUIDs and GUIDs. The ColdFusion UUID format is 8-4-4-16. This might seem a little dense, but I am sure some of you are curious.
The UUID value alone could be your "ticket", but to add one more level of complexity, compound the value with ColdFusion's HASH function. This function converts the UUID to a 32-byte, hexadecimal string using the MD5 algorithm. The MD5 algorithm is not possible to convert back to the source string, and thus provide security for transporting data from client to server.
<cffunction name="setTicket" access="remote" returntype="any"> <cfargument name="userID" type="any" required="yes"> <CFSCRIPT> // create a new Ticket Object that will store the ticket info ticket_Obj = structNew(); // set the ticket using CreateUUID and HASH ticket_Obj.ticket = Hash(CreateUUID()); // set the initial expiry Date ticket_Obj.expiry = CreateODBCDateTime(DateAdd("yyyy",10,now())); </CFSCRIPT> <!--- place the ticket into the database. ---> <CFQUERY NAME="q_setTicket" Datasource="myFlashComDb.mdb"> INSERT INTO Users_ticket (ticket, UserID, expiry) VALUES('#ticket_Obj.ticket#', #arguments.userID#, #ticket_Obj.expiry#); </CFQUERY> <CFRETURN ticket_Obj> </cffunction>
This is only one method you can use to archive the persistent data. Another approach might be to store this information in a persistent server scope such as the Application, Server, Client, or Session Scope.
Method #3: "findTicket"
Now with all that security and encryption technology, a service function is required to match the ticket that will be transferred from Flash to FCS with the user data. This function will be called by the Flash Communication Server. But the API is generic enough that you could use it anywhere.
When called, this function receives a value stored in the "ticket_hash" argument. Using CFQuery, a simple lookup is all you need to do to determine if the ticket is valid. To enforce the expiry date, add a WHERE condition that ensures the ticket is not out-of-date (preventing any hackers from sending bogus tickets to the server).
The following script takes the simple lookup one step further, and using an INNER JOIN, it makes the relationship back to the Users table to capture the first and last name of the user's record.
When the CFQuery is finished, construct a return object (return_obj) structure with two keys, USERNAME and ISTICKETOK. This object with these two keys will be returned to the Flash Communication Server as an ActionScript Object. Figure 6 shows the complete structure of the return_obj.
<cffunction name="findTicket" access="remote" returntype="any"> <cfargument name="ticket_hash" type="any" required="yes"> <CFQUERY NAME="q_getUser" Datasource="myFlashComDb.mdb"> SELECT Users.fname, Users.lname FROM Users INNER JOIN Users_Ticket ON Users.UserID = Users_Ticket.UserID WHERE users_Ticket.ticket = '#arguments.ticket_hash#' and users_Ticket.expiry > now(); </CFQUERY> <CFSCRIPT> return_obj = structNew(); return_obj.userName = q_getUser.fname & " " & q_getUser.lname; if (q_getUser.recordCount neq 0) return_obj.isTicketOK = true; else return_obj.isTicketOK = false; /* Return the Object to the Caller */ return return_obj; </CFSCRIPT> </cffunction>
Figure 6 The ColdFusion Structure returned by the findTicket method is assembled automatically by Flash Remoting MX into an ActionScript Object with two properties.
Method #4 (optional): "updateTicket"
This is an optional method that will let you easily update the expiry date of any ticket. Simply pass the ticket and the amount of hours (from now) that the ticket will expire. It could be used in an application.onDisconnect event in SSAS, or by an administrative application. It is not used in this project, but it was built and might be a handy script for some of you.
<cffunction name="updateTicket" access="remote" returntype="boolean"> <cfargument name="ticket_hash" type="any" required="yes"> <cfargument name="new_expiry" type="numeric" required="false" default="1"> <CFQUERY NAME="q_getUser" Datasource="myFlashComDb.mdb"> UPDATE users_Ticket set Expiry = #CreateODBCDateTime(DateAdd("h",new_expiry,now()))# where ticket = '#ticket_hash#' </CFQUERY> <CFReturn true> </cffunction>
If you would like to test your CFC, you can do so by calling the file within a web browser using this URL: http://localhost/flashcom/applications/informIT/FCS_Security.cfc
Running this file will output a full documentation of the component. You could also test the CFC using the <CFINVOKE> tag or the CreateObject function within a ColdFusion (CFM) file. Now that the ColdFusion Component is ready, let's move on to building the Flash movie.