Question

Whats the easiest way of preventing multiple logins in cf?

<cfcomponent>
<cfset This.name = "Name">

<cfset This.Sessionmanagement="True">
<cfset This.loginstorage="session">
<cfset This.sessionTimeout = "#CreateTimeSpan(0, 0, 50, 0)#"> 
<cfset This.applicationtimeout="#createtimespan(0,0,50,0)#">
<cfset This.scriptProtect = "All">

<cffunction name="OnRequestStart">
    <cfargument name = "request" required="true"/>

    <cfif IsDefined("Form.logout")> 

        <cflogout>

        <cfset StructClear(Session)>

        <cflocation url="/" addtoken="no">

    </cfif>

    <cflogin>
        <cfif NOT IsDefined("cflogin")>
            <cfinclude template="loginform.cfm">
            <cfabort>


        <cfelse>
            <cfif cflogin.name IS "" OR cflogin.password IS "">
                <cfoutput>
                    You must enter text in both the User Name and Password fields.
                </cfoutput>
                <cfinclude template="loginform.cfm">
                <cfabort>
            <cfelse>
                <cfquery name="loginQuery" dataSource="datadsn">
                SELECT *
                FROM userlogin
                WHERE
                UserID = <cfqueryparam value="#cflogin.name#" cfsqltype="CF_SQL_VARCHAR"> 
                AND Password = <cfqueryparam value="#hash(cflogin.password)#" cfsqltype="CF_SQL_VARCHAR">
                AND trenabled = <cfqueryparam value="1" cfsqltype="CF_SQL_VARCHAR">
<!--- Project ID--->
                AND projectid = <cfqueryparam value="23" cfsqltype="CF_SQL_VARCHAR">
                </cfquery>

                <cfset loginpass = #hash(cflogin.password)#>

                <cfset comparison = Compare(loginQuery.Password, loginpass)>

                <cfif loginQuery.trRoles NEQ "" AND comparison EQ 0>

                <cfloginuser name="#cflogin.name#" Password = "#loginpass#" roles="#loginQuery.trRoles#">

                <cfelse>
                    <cfoutput>
                        Your login information is not valid.<br>
                        Please Try again.
                    </cfoutput>    
                    <cfinclude template="loginform.cfm">
                    <cfabort>
                </cfif>
            </cfif>    
        </cfif>
    </cflogin>

    <cfif GetAuthUser() NEQ "">
        <cfoutput>
             <form method="Post">
                <input type="submit" Name="Logout" value="Logout">
            </form>
        </cfoutput>

    </cfif>

</cffunction>

<cffunction name="onSessionEnd" returnType="void">


</cffunction>

</cfcomponent>
Was it helpful?

Solution

Where I work they have strict requirements about limiting the number of logins by a single user to a single application. I approached this problem this like this:

1) Have a user login table that holds user info and a field that called "last update" and "Logged in". When the user logs in the "last update" with the current time date and the "logged in" with a 1. This prevents that user from logging in again.

2) Create a jquery ajax call to update the database field "last update" with a new time date stamp. This happens on a schedule (like every 1 min).

3) Last thing I had to do was schedule a task that checked to see if last update for active logins (in the database) was greater than a fixed period of time, if it was that users "Logged in" status was changed from 1 to 0 (allowing them to login again). The reason why this is important is you cannot assume the user will always click "logout" when they leave. Sometimes they just close their browser or navigate away. When this happens if they attempted to come back to the application they would not be able to login again (because the database thinks they are logged in already).

Hope this gets you going in the right direction.

OTHER TIPS

The easiest way I found to do this is to tie into the underlying java session scope in ColdFusion and look for an existing login for the one you have.

If it's there, kick out/expire the other session and let the current one in.

Here's an example from my code. Do note that there are different ways to kill/end a session each with their own pros/cons. This example was for an inherited codebase.

getLogin.fld_userid is what the attempted login ID is from the html form.

I have this code run during "on login" before I initialize the session variables.

<!---code for 1user per login  --->  
<cfset liveSessions = createObject("java","coldfusion.runtime.SessionTracker")>
<cfset activesessions = liveSessions.getSessionCollection(YOUR_DATA_SOURCE_NAME)>

<cfloop item="loopSession" collection="#activesessions#">
  <cfscript>
    thisSession = activesessions[loopSession];

    if(StructIsEmpty(thisSession)) {
      // do nothing
    } else {
      if(isDefined("thisSession.loginUserid")) {
        thisUser = thisSession.loginuserid;
        if(thisSession.loginuserid EQ getlogin.fldUser_ID) {
          thisSession.XXAutoToken="";
          //structClear(thisSession);
          //cflocation(theUrl:"index.cfm?home.welcome");
          thisSession.setMaxInactiveInterval(1);
          break;
        }
      }
    }
  </cfscript>
</cfloop>

Based on Jas'z Answer:

I would assume from their answer that the commented techniques didn't achieve what they desired at the time (2010).

Per some googling, the session method (from the underlying java) setMaxInactiveInterval may no longer work (as it appears using Lucee 5 and MySQL database for session storage)

I tried many things to clear the session, such as structClear, setting the session to {}, setting the session to the bare properties {cfid, cftoken...}, and none of these worked.

The only thing that did work was setting or changing individual properties of the session, such as thisSession.loggedIn.

Uses for this could include allowing users to see and control where else they're logged in.

<cfscript>
  liveSessions = createObject("java","coldfusion.runtime.SessionTracker");
  activeSessions = liveSessions.getSessionCollection(application.applicationName);

  for (s in activeSessions) {
    thisSession = activeSessions[s];

    if (!StructIsEmpty(thisSession)) {
      // Change loggedIn to whatever property identifies a login.
      if (isDefined("thisSession.loggedIn") && thisSession.loggedIn &&
        thisSession.UserID == form.UserID) {
        // Change the UserID line above to whatever match you're looking for
        if(thisSession.UserID == form.UserID) {
          // Change loggedIn to whatever property identifies a login.
          lock scope="session" timeout="5" {
            thisSession.loggedIn = 0;
          }
          break;
        }
      }
    }
  }
</cfscript>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top