August 08, 2012

Limiting user sessions(Set Timeout For User Session)

Limiting user sessions

Our company has a limited number of AX user licenses, as most companies will. Some people like to open multiple sessions (and eat up licenses) while they're working. We wanted some way for the system to prevent this from happening.
To achieve this I created a table called UserSessionLimits. It has a field called UserID (extended data type is userId) and this is a mandatory field. It has another field called MaxSessions (this is an integer) and it also is mandatory. The index is UserIDx, it contains userid and it is unique.
The code that accesses this table is written so that if a user is not in this table, then they are limited to one session, so add users to this table if they are exceptions and you want them to be able to have more than one session open.
Add code to the "Info" class, in the startup() method. The Info class can only be accessed by going to the System Documentation area of the AOT.
In the startup method, at the top, I placed this code:

select count(recid) from sysClientSessions
where sysClientSessions.userId == curuserid() &&
sysClientSessions.Status == 1 &&
sysClientSessions.clientType == 0;
if(sysClientSessions.RecId > UserSessionLimits::getMaxSessions(curUserid()))
{
box::stop(strfmt("You have exceeded your session limit of %1, the application will now close",
UserSessionLimits::GetMaxSessions(curUserid())));
appl.globalcache().set(classstr(info),identifierStr(AutoLogoff), true);
this.shutDown(true);
}

By searching only for clientType = 0, you will only be looking for "User" sessions. Web sessions or worker sessions (batches that are running) will not be affected.
There have been times that people have gotten around this. They quickly opened two sessions immediately one after the other. If they are simultaneously opened, it's hard to catch. Also, sometimes this locks people out. If they were doing something and AX shut down on them or their system froze, sometimes it takes some time for the session to end for them to get back in again. Your network administrator can control when inactive sessions time out.

We also set automatic shutdown (in user options) to 60 minutes. So if their session is inactive for 60 minutes, it will close.

See also,


4 comments:

  1. Hi
    I have tried this and this doesn't work for normal user(who doesn't have access to "user info" form for in Admin Security group).
    this works fine for all other users. it looks like normal users don't have permission to acres SysClientSessions table.
    any idea please?

    Thanks
    Sam

    ReplyDelete
  2. Hi,

    This code is not suppose to use by every one. ASk your technical to write this code in appropriate class, it must work. I would suggest try this in DEV environment first than go for UAT ans Live.

    ReplyDelete
  3. Thanks for this code. I tried it and I had the same issue as Sam for normal users. I modified it to use the XSession class instead of the sysClientSession table. The code below works for my normal users too (placed in the startupPost method). ~Karin

    void startupPost()
    {
    userid CurUser = curUserId();
    boolean AdminUser = UserInfoHelp::userInUserGroup(CurUser, "Admin");
    int SessionLimit;
    int counter;
    int num = 0;
    int maxSessions = Info::licensedUsersTotal();
    xSession sessionUser;
    str SessionUserId;
    ;

    if (AdminUser)
    {
    SessionLimit = 0; //unlimited for Admin users
    }
    else
    {
    sessionLimit = UserSessionLimitsExceptions::getMaxSessions(curUser);

    if (sessionLimit == 0)
    {
    sessionLimit = 1; //Default 1 for normal users if nothing else specified
    }
    }

    if (sessionLimit > 0 && clientKind() == ClientType::Client)
    {

    for(counter = 1; counter < maxSessions;counter++)
    {
    sessionUser = new xSession(counter, true);
    SessionuserId = sessionUser.userId();
    if(sessionUser && SessionUserId == curUser
    && sessionUser.clientKind() == ClientType::Client)
    {
    num++;
    if (num > sessionLimit)
    {
    box::stop(strfmt("You have exceeded your session limit of %1, the application will now close",
    SessionLimit));
    appl.globalcache().set(classstr(info),identifierStr(AutoLogoff), true);
    this.shutDown(true);
    }
    }

    }
    }

    }

    ReplyDelete

Thanks