If Else query is empty - coldfusion

I am using CFLDAP to have users get authenticated using active directory. I am trying to write an if statement in case the users information does not come back as authenticated. I thought I could check by using <cfif AuthenticateUser.RecordCount gt 0> which is working as long as the information is correct but if the wrong information is entered and nothing is authenticated it is not running the else statement. Any help with this would be greatly appreciated!
<cfldap action="query"
name="AuthenticateUser"
attributes="dn,mail,givenname,sn,samaccountname,memberof"
start="DC=domain,DC=net"
filter="(&(objectclass=user)(samAccountName=#trim(form.user_name)#))"
server="servername"
Port="389"
username="tc\#trim(form.user_name)#"
password="#trim(form.user_pass)#">
<cfoutput>#AuthenticateUser.RecordCount#</cfoutput>
<!--- Get all records from the database that match this users credentials --->
<cfquery name="userVerify" datasource="test">
SELECT *
FROM dbo.Users
WHERE user_name = <cfqueryparam value="#AuthenticateUser.samaccountname#" cfsqltype="cf_sql_varchar" />
</cfquery>
<cfif AuthenticateUser.RecordCount gt 0>
<!--- This user has logged in correctly, change the value of the session.allowin value --->
<cfset session.allowin = "True" />
<cfset session.employee_number = userVerify.employee_number />
<!--- Now welcome user and redirect to "index.html" --->
<script>
self.location="../dashboard/dashboard.cfm";
</script>
<cfelse>
<!--- this user did not log in correctly, alert and redirect to the login page --->
<script>
alert("Your credentials could not be verified, please try again!");
self.location="Javascript:history.go(-1)";
</script>
</cfif>
I have also tried: <cfif len(AuthenticateUser)>

This is how I do it. I try to run a query against our domain using the supplied username and password. If the supplied username and password are not valid, an error is generated.
<cftry>
<cfldap action="Query"
name="ADResult"
attributes="dn"
start="DC=domain,DC=net"
filter="sAMAccountName=administrator"
server="servername"
scope = "subtree"
username="#arguments.username#"
password="#arguments.password#" />
<cfset isAuthenticated = true />
<cfcatch type="any">
<cfset isAuthenticated = false />
</cfcatch>
</cftry>
<cfreturn isAuthenticated />
I wrap this up in a function called "authenticate" and expose it via a web service that I call from my apps. If I then need additional details about the user (mail, givenName, etc), I have another function in the same web service that I will call after I am sure the user has been authenticated. Note that in this other function I'm using my administrator username and password to run the query.
<cfldap action="Query"
name="ADResult"
attributes="mail,givenName"
start="DC=domain,DC=net"
filter="sAMAccountName=#arguments.username#"
server="servername"
scope = "subtree"
username="administrator"
password="myAdminPassword" />
I take the results of this, populate a query object or a structure, and return that to the calling function.
So the entire process sort of looks like this:
<cfset objAD = createobject("webservice", "http://mywebservice.com") />
<cfset isAuthenticated = objAD.authenticate(form.username, form.password) />
<cfif isAuthenticated>
<cfset userDetails = objAD.getUserDetails(form.username)>
</cfif>
Hope this helps.

This is a formatted comment. You are trying to do too much at once. Go one step at a time. Start with this:
<cfdump var="before cfldap tag<br />">
<cfldap action="query"
name="AuthenticateUser"
etc
>
<cfdump var="after cfldap tag<br />">
<cfdump var = "#AuthenticateUser#">
<cfdump var="after cfdump<br />">
Run this code with both valid and not valid credentials. Look at what you get. React accordingly.

I think it throws an error when the query fails. Try this:
<cftry>
<cfldap action="query"
name="AuthenticateUser"
attributes="dn,mail,givenname,sn,samaccountname,memberof"
start="DC=domain,DC=net"
filter="(&(objectclass=user)(samAccountName=#trim(form.user_name)#))"
server="servername"
Port="389"
username="tc\#trim(form.user_name)#"
password="#trim(form.user_pass)#">
<cfset LoginStatus = "Success">
<cfcatch type="any">
<cfset LoginStatus = "Failed">
</cfcatch>
</cftry>
Then your cfif would be something like this:
<cfif LoginStatus eq "Success">
<!--- This user has logged in correctly, change the value of the session.allowin value --->
<cfset session.allowin = "True" />
<cfset session.employee_number = userVerify.employee_number />
<!--- Now welcome user and redirect to "index.html" --->
<script>
self.location="../dashboard/dashboard.cfm";
</script>
<cfelse>
<!--- this user did not log in correctly, alert and redirect to the login page --->
<script>
alert("Your credentials could not be verified, please try again!");
self.location="Javascript:history.go(-1)";
</script>
</cfif>
I think this works on CF9.

Related

ColdFusion Link to Previous Page Clears only that Page Session Variables

I have a page (form) set up like this:
<cfif not structKeyExists(session, "checkout")>
<cflocation url="ownerInfo.cfm" addToken="false">
</cfif>
<cfif not structKeyExists(session.checkout, "vehicle")>
<cfset session.checkout.vehicle = {ownership=""}
<cfparam name="form.ownership" default="#session.checkout.vehicle.ownership#">
<cfif structKeyExists(form, "submit")>
<cfset errors = []>
<cfif not arrayLen(errors)>
<cfset session.checkout.vehicle = {ownership=form.ownership}
<cflocation url="ownerCheck.cfm" addToken="false">
</cfif>
</cfif>
I am trying to figure out how I can reset this form by having a link on another page that when this page is linked back to it will reset all the session variables to null making the entire page needing to be filled out again.
This is what I have tried but am unsuccessful.
<cfif session.checkout.vehicle.ownership != null />
<cfset session.checkout.vehicle.ownership = null />
</cfif>
I cannot use <cfset StructClear(Session)> because I do not want all the session variables cleared from the previous pages only want this page to reset.(Not All Pages or All Session Variables). Any help with this would be greatly appreciated!
You can do using structDelete(structure,key)
<cfif session.checkout.vehicle.ownership != null />
<cfset structDelete(session.checkout.vehicle,'ownership ')>
</cfif>
If you want to clear the session scope variables if the ownership key already exists in the session scope then you can do:
<cfif structKeyExists(session.checkout.vehicle, "ownership")>
<!--- struct key exists so delete it --->
<cfset structDelete(session.checkout.vehicle, "ownership")>
</cfif>
You can actually just do:
<cfif structKeyExists(session.checkout, "vehicle")>
<!--- try and delete ownership key might not exist --->
<cfset structDelete(session.checkout.vehicle, "ownership")>
</cfif>
As long as the parent scope exists, you can try and delete the ownership key without first checking that it exists.
If you want to know if the key did exist then structDelete accepts a 3rd boolean parameter so it'll return true if it did exists and false if it didn't.
<cfset didExist = structDelete(session.checkout.vehicle, "ownership", true)>
An alternative approach to solving your problem would be to reset the form if it's not a form (POST) submission. So you'd do:
<cfif structKeyExists(form, "submit")>
<!--- form has been submitted store values in session and redirect... -->
<cfelse>
<!--- form not submitted so clear the session vars... --->
</cfif>

Setting up Session variable in Application.cfc

Hi I'm very new with ColdFusion 10 especially with Application.cfc. It is very confusing.
I created Application.cfc and inside this cfc I created the following:
My questions are:
1. Why do I get session error? (see my codes below)
2. What should I put in sessionEnd function?
<!--- Application.cfc --->
<CFCOMPONENT displayname="Application" output="true">
<cfset THIS.Name = "MyTestApp" />
<cfset THIS.ApplicationTimeout = CreateTimeSpan(0,0,60,0) />
<cfset THIS.SessionManagement = true />
<cfset THIS.SessionTimeout = CreateTimeSpan( 0, 0, 30, 0 ) />
<cfset THIS.SetClientCookies = false />
<cfset THIS.SetClientCookies = false />
<cffunction name="OnApplicationStart" access="public"
returntype="boolean" output="false">
<cfset application.Main_DSN = "MyTestDB">
</cffunction>
<cffunction name="onApplicationEnd" output="false">
<cfargument name="applicationScope" required="true">
</cffunction>
<cffunction name="OnSessionStart" access="public" returntype="void" output="false"
hint="Fires when user session initializes">
<cfset session.loggedin = "NO">
<cfset session.username = "">
<cfset session.userrights = "">
<cfset session.usergroup = "">
</cffunction>
<!--- After user login, I have checklogin.cfm --->
<cfif mylogin NEQ true><!--- Login failed, go redirect to login page --->
<cflocation url="login.cfm">
<cfelse>
<cfset session.loggedin = "YES"><!--- ??? error: see below --->
<cfset session.username = "#Trim(Form.username)#">
<cfset session.userrights = "#Trim(Form.userrights )#">
<cfset session.usergroup = "#Trim(Form.usergroup)#">
</cfif>
<cffunction name="onSessionEnd">
<!--- Not sure what can I put in here????? --->
</cffunction>
Your login code is outside any of the event handlers in your Application.cfc file, so that code will run first... before any of the event handlers!
The execution sequence of code in Application.cfc is:
code outside of any event handler (irrespective of where it is in the file)
onApplicationStart()
onSessionStart()
onRequestStart()
etc
So you cannot have code referencing the session scope (or application scope for that matter) outside the other event handlers. You can only start using session variables once onSessionStart() has fired. Not before.
What is the error message that you are getting?
You can really put anything in the session end. Anything that you would need to run to clean up after a session.
Maybe you want to update a log or send an email, clear a cookie, or redirect to a certain page.
EDIT:
Is everything else in the Application.cfc working for you? It seems like the onSessionStart event is not firing.
EDIT 2:*
Sorry for doing this via an answer but I need more rep to leave comments.
The session should start as soon as you connect to the application, you do not need to wait to be "logged in" as in verify credentials.
If the session variables do not exist then the event is not firing for some reason. Make sure you have the file name correctly and it is in the root folder of the application.
EDIT 3:
Your login code is not in the onSessionStart function, not in any function. Unless I misunderstood your comment and you were saying that code section is in the "checklogin.cfm" file and not in the Application.cfc file.
EDIT 4:
I need to jump on a client call but I can help some more after. We might need to take a look at part of the checklogin.cfm file.
EDIT 5:
Any luck?
EDIT 6:
Sorry for the delay, volume is ramping up this afternoon.
At this point I think I would either need to see the code that is doing the validation checking or ask if you are sure the validation is working correctly.
I assume you are connecting to a database, if you take the query you are using to verify the login credentials and run it in SQL server or whatnot inserting the values you would type into the form, do you get any results?
EDIT 7:
Figure it out, OP?

cfindex custom fields that are used for display no indexible

Currently working with Coldfusion 10 and cfsearch.
After many hours of trial and error, I have managed to get cfindex to collect all my custom field data so that it is available to me as fields for the output on my search results page.
My only issue now, is that the search will be able to search for things like true / false strings and it will return in the search results.
I could run a QoQ to strip those out, im just wondering if anyone has any suggestions for adding fields to an index but not having them searchable.
Any ideas greatly appreciated
my current code is below
<cftry>
<!-- create new searchable collection -->
<!--- cfcollection action= "create" collection="testsearch" path= "#expandPath('/assets/scripts/server/solr/')#" ---->
<cfcollection action= "list" name="collectionlist">
<cfdump var="#collectionlist#">
<cfquery name="MyQuery" datasource="#request.DSN#" maxrows="10">
SELECT *
FROM Store_products
</cfquery>
<cfdump var="#myQuery#">
<cfset myAttr = structNew()>
<cfset variables.columns = "COST,CREATEDDATE,CUSTOM_MESSAGE,CUSTOM_MESSAGE_LENGTH,DISPLAYNAME,DONTINCLUDEINSTOCKUPDATE,FEATUREDPRODUCT,FINALDAYS,FREEDELIVERY,HEIGHT,HTMLMETADESCRIPTION,HTMLMETAKEYWORDS,IMAGE1,IMAGE10,IMAGE2,IMAGE3,IMAGE4,IMAGE5,IMAGE6,IMAGE7,IMAGE8,IMAGE9,ISBUNDLE,ISNEWPRODUCT,ISONLINE,ISONSALE,ISSILENT,LONGDESCRIPTION,MANUFACTURER,NOVOUCHERS,ONLINEEXCLUSIVE,PARTNUMBER,PRICE,PRICELEVEL1,PRICELEVEL10,PRICELEVEL11,PRICELEVEL12,PRICELEVEL13,PRICELEVEL14,PRICELEVEL15,PRICELEVEL2,PRICELEVEL3,PRICELEVEL4,PRICELEVEL5,PRICELEVEL6,PRICELEVEL7,PRICELEVEL8,PRICELEVEL9,PRODUCTCATEGORY,PRODUCTCOLOR,PRODUCTMATERIAL,PRODUCTNAME,PRODUCTSIZE,PRODUCTSTYLE,PRODUCTTITLE,PRODUCTVIEWS,RRP,SALEEND,SALEPRICE,SALESTART,SHORTDESCRIPTION,SOLDOUT,STOCKQUANTITY,STORESORTORDER,TAXEXEMPT,VOLUME,WEIGHT,WIDTH">
<cfloop from="1" to="#ListLen(variables.columns,',')#" index="idx">
<cfset myAttr[listGetAt(variables.columns,idx,',') & "_s"] = listGetAt(variables.columns,idx,',') >
</cfloop>
<cfindex attributecollection="#myAttr#" action="update" collection="testsearch" type="custom" body="DISPLAYNAME,HTMLMETADESCRIPTION,HTMLMETAKEYWORDS,LONGDESCRIPTION,MANUFACTURER,PARTNUMBER,PRODUCTNAME,PRODUCTTITLE,RRP,SHORTDESCRIPTION" query="MyQuery" key= "productname">
<cfsearch name="searchResults" collection="testsearch" criteria="false" >
<cfdump var="#searchResults#">
<cfcatch type="any">
<cfdump var="#cfcatch#">
</cfcatch>
</cftry>

Is the CFDUMP tag modifiable?

With ColdFusion MX7 if we encounter an exception we send an email to the development team containing dumps of the various data scopes including the form structure.
This works great for debugging except in the case of an error when the user logs in. We end up getting the password printed out.
So, the question is, is there a way to modify the CFDUMP file so that it filters the password value out of the form object?
Naturally we could put it in the same code that sends the email, however it would be ideal to put it in the CFDUMP file so that we do not have to worry about it showing up in other spots.
I have located the CFDUMP file and it seems to be binary, so I'm guessing we can't do it.
You can copy the dump.cfm file to dumporiginal.cfm, and then make a new dump.cfm that calls dumporiginal.cfm.
<!---
So that it won't execute twice if you
have a closing slash (<cfdump ... />)
--->
<cfif thisTag.executionMode neq "start">
<cfexit method="exitTag" />
</cfif>
<!---
defaults for optional attributes, taken from the docs
http://livedocs.adobe.com/coldfusion/8/htmldocs/Tags_d-e_08.html
--->
<cfparam name="attributes.expand" default="yes" />
<cfparam name="attributes.format" default="html" />
<cfparam name="attributes.hide" default="all" />
<cfparam name="attributes.keys" default="9999" />
<cfparam name="attributes.label" default="" />
<cfparam name="attributes.metainfo" default="yes" />
<cfparam name="attributes.output" default="browser" />
<cfparam name="attributes.show" default="all" />
<cfparam name="attributes.showUDFs" default="yes" />
<cfparam name="attributes.top" default="9999" />
<!--- Hide the password, but store its value to put it back at the end --->
<cfif isStruct(attributes.var) and structKeyExists(attributes.var, 'password')>
<cfset originalPassword = attributes.var.password />
<cfset attributes.var.password = "{hidden by customized cfdump}"/>
</cfif>
<!---
Call the original cfdump.
Which attributes you pass depends on CF version.
--->
<cfswitch expression="#listFirst(server.coldfusion.productVersion)#">
<cfcase value="6">
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
hide = "#attributes.hide#"
label = "#attributes.label#"
>
</cfcase>
<cfcase value="7">
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
hide = "#attributes.hide#"
label = "#attributes.label#"
top = "#attributes.top#"
>
</cfcase>
<cfdefaultcase>
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
format = "#attributes.format#"
hide = "#attributes.hide#"
keys = "#attributes.keys#"
label = "#attributes.label#"
metainfo = "#attributes.metainfo#"
output = "#attributes.output#"
show = "#attributes.show#"
showUDFs = "#attributes.showUDFs#"
top = "#attributes.top#"
>
</cfdefaultcase>
</cfswitch>
<!--- Restore the password, in case it's read after cfdump call --->
<cfif isDefined("originalPassword")>
<cfset attributes.var.password = originalPassword />
</cfif>
No, I don't think there is a way to modify <cfdump>'s behavior. I can't be sure, obviously. It's thinkable that such a hack exists, though it's not necessarily recommendable.
Why not go with a simple:
<cftry>
<cfset DoSomethingThatFails()>
<cfcatch>
<cfif StructKeyExists(FORM, "Password")>
<cfset FORM.Password = "***">
</cfif>
<cfdump var="#FORM#">
</cfcatch>
</cftry>
CFDUMP began life as a custom tag (CF_DUMP) way back in the CF5 days. You could always get the code for that custom tag and modify it to your needs and use that instead of the built-in tag.
Is it only the password that is a problem of showing? If so, perhaps the solution is to salt/hash the password? That I think is good practice anyway.
http://blog.mxunit.org/2009/06/look-ma-no-password-secure-hashing-in.html

Sharing login credentials between ColdFusion servers?

If I have multiple CF8 servers, can a user login on one server, but share the login credential among all servers (no re-login required)?
Maybe question is about sharing session? This can be done using serialized J2EE sessions or using shared client variables.
For example, this can be done in following way.
Create empty database on one of servers (I've created MySQL one). Create datasources pointing to this DB on all CF servers. Use this datasource as Server Settings > Client Variables > client sessions storage with name SharedSessions (we'll use it later).
If we're using cflogin in Application.cfm on all servers, it's code can look this (simplified) way:
<cfapplication
name="shared_session_test"
sessionManagement="true"
clientmanagement="true"
clientstorage="SharedSessions" />
<cflogin>
<cfif IsDefined( "cflogin" ) and cflogin.name eq "admin" and cflogin.password eq "admin">
<cfset user_roles = "administrators" />
<cfset user_name = cflogin.name />
<cfset user_password = cflogin.password />
</cfif>
<cfif IsDefined( "user_roles" )>
<!--- push login params into shared client scope --->
<cfset CLIENT.user_roles = user_roles />
<cfset CLIENT.user_name = user_name />
<cfset CLIENT.user_password = user_password />
<cfelseif IsDefined( "CLIENT.user_roles" )>
<!--- restore login params from shared client scope --->
<cfset user_roles = CLIENT.user_roles />
<cfset user_name = CLIENT.user_name />
<cfset user_password = CLIENT.user_password />
</cfif>
<cfif IsDefined( "user_roles" )>
<cfloginuser name="#user_name#" password="#user_password#" roles="#user_roles#">
<cfelse>
<!--- authentication failed - send back 401 --->
<cfsetting enablecfoutputonly="yes" showdebugoutput="no">
<cfheader statuscode="401">
<cfheader name="WWW-Authenticate" value="Basic realm=""MySecurity""">
<cfoutput>Not authorized</cfoutput>
<cfabort />
</cfif>
</cflogin>
<cfoutput><p>other.server.com</p></cfoutput>
Now these show the same on both servers:
<cfdump var="#getAuthUser()#">
<cfdump var="#CLIENT#">
Sure, there's much to do here to make process better and more secure, just described the general idea.
Hope this helps.