ColdFusion MX 7 Login Security (Page 6 of 13)
Let's say the user realizes his error and enters a valid username. The onRequestStart method will again notice the submittal of the form and include the authenticate.cfm template.
36. <cfif qryGetUserDetails.RecordCount eq 0> 41. <cfset variables.errorMessage = "The Username you provided, <b>" & FORM.Username & "</b>, is an invalid Username."> 42. <cfelse> 44. <cfset variables.hashedPassword = Hash(FORM.Password)> 45. <cfif variables.hashedPassword neq qryGetUserDetails.Password> 47. <cfset variables.errorMessage = "The Password you supplied for user <b>" & FORM.Username & "</b> was incorrect."> 48. <cfelse> 52. <cfquery name="qryUpdateLastLoginTS" datasource="##request.datasource##"> 53. UPDATE Users 54. SET LastLogin_TS = ##CreateODBCDateTime(Now())## 55. WHERE ID = ##qryGetUserDetails.ID## 56. </cfquery> 63. <cfset request.User.LoggedIn = "1"> 64. <cfset request.User.Username = FORM.Username> 65. <cfset request.User.FirstName = qryGetUserDetails.FirstName> 66. <cfset request.User.LastName = qryGetUserDetails.LastName> 67. <cfset request.User.LastLogin = qryGetUserDetails.LastLogin_TS> 68. <cfset tmpMessage = "You were last here on " & DateFormat(qryGetUserDetails.LastLogin_TS, "mm.dd.yyyy") & " at " & TimeFormat(qryGetUserDetails.LastLogin_TS, "hh:mm tt") & "."> 69. <cfset request.User.LoginMessage = IIF(qryGetUserDetails.LastLogin_TS neq "" "tmpMessage", DE("This is your first visit!"))> 70. </cfif> 71. </cfif>
This time, the conditional logic on line 36 will evaluate to FALSE and the else statement will execute. On line 44 we create a local variable that holds the hashed value of the FORM.Password variable. The Hash() function is built-in to the ColdFusion server and creates a 32-bit one-way encrypted string using the MD5 algorithm (NOTE: The MD5 algorithm is the default in CFMX7 but many other algorithms are supported and available. See the CFMX7 documentation for more information). No matter what set of characters you feed the Hash() function, it will always return a 32-bit string (when the MD5 algorithm is used). One-way encryption means there is no way to decrypt the encrypted string. The Hash() function is also case-sensitive. It will return one 32-bit string for "admin" and a different string for "AdMiN." Once we've compared the encrypted password entered by the user with the password stored in the database (line 45) one of two things happens. If the password is entered incorrectly we create the local variable variables.errorMessage which will then be used to display the password error in our login form (this same scenario was outlined on the previous page when the user entered a non-existent username). If the password is entered correctly, we update the "last login" timestamp for the user, and we create a Request scope structure that temporarily holds any information we will later duplicate into a Session structure. Again, page processing will be returned to the onRequestStart method and the conditional logic on line 108 will be executed.PREVIOUS | NEXT