Monday, 22 December 2025

Session Count-Based Concurrent Login Management in ASP.NET WebForms

Leave a Comment

Limiting the amount of concurrent logins per user is a typical practice in many real-world applications, including banking portals, trading platforms, admin panels, and business systems.
Data inconsistencies, license abuse, and security problems might result from permitting infinite logins with the same credentials.


This article describes a traditional concurrent login/session-count control requirement, explores several solutions, and offers a simple ASP.NET WebForms + SQL Server solution with functioning logic and output explanation.

Problem Statement

  • A single user account should be allowed to log in from only N sessions (example: 2, 3, or 4).

  • If the user logs in again after reaching the limit:

    • Either deny login OR

    • Automatically terminate the oldest inactive session and allow new login.

  • Sessions may remain active if:

    • Browser is closed suddenly

    • User forgets to log out

  • The system must handle these cases automatically.

Requirements Summary

  • Allow configurable session count per user

  • Track:

    • Login time

    • Last activity

    • Active / inactive status

  • Automatically expire unused sessions

  • Ensure latest active users are not disturbed

Possible Approaches

Option 1: ASP.NET Session Only (Not Recommended )

  • Uses Session[] variables

  • Fails when:

    • Browser crashes

    • Multiple devices used

  • No central control

Not suitable for concurrent login control

Option 2: Database-Based Session Tracking (Recommended )

  • Store sessions in a database table

  • Track activity per login

  • Kill old sessions safely

This is the correct and professional approach

Database Design

adminmaster Table

Stores user details and allowed session count.

CREATE TABLE adminmaster
(
    Srno INT PRIMARY KEY,
    userid VARCHAR(50),
    password VARCHAR(50),
    SessionCount INT DEFAULT 3
);

UserSessions Table

Tracks each login session.

CREATE TABLE UserSessions
(
    SessionId UNIQUEIDENTIFIER PRIMARY KEY,
    UserSrno INT NOT NULL,
    LoginTime DATETIME,
    LastActivity DATETIME,
    IsActive BIT,
    CONSTRAINT FK_UserSession_Admin
        FOREIGN KEY (UserSrno) REFERENCES adminmaster(Srno)
);

Concept Used

1. GUID-Based Session Identification

  • Each login creates a unique SessionId

  • Avoids conflicts

  • Safe across multiple users and devices

2. Least Recently Used (LRU) Strategy

  • Sessions ordered by LastActivity

  • Oldest inactive session is terminated first

3. Configurable Session Limit

  • Each user has a different SessionCount

  • Can be changed without code modification

Login Flow Logic

  1. Validate username & password

  2. Read allowed session count

  3. Fetch active sessions

  4. If session limit reached:

    • Kill the oldest active session

  5. Create a new session

  6. Allow login

ASP.NET WebForms Login Code

// Validate user
string sqlqry = @"
SELECT Srno, userid, SessionCount
FROM adminmaster (NOLOCK)
WHERE userid=@UserId AND password=@passwrd";

DataSet ds = SqlHelper.ExecuteDataset(con, CommandType.Text, sqlqry, param);

if (ds == null || ds.Tables[0].Rows.Count == 0)
{
    ErrLbl.Text = "Invalid UserID or Password";
    return;
}

// User is valid
DataRow row = ds.Tables[0].Rows[0];
int userSrno = Convert.ToInt32(row["Srno"]);
int maxSession = row["SessionCount"] == DBNull.Value ? 0 : Convert.ToInt32(row["SessionCount"]);

// Get active sessions
string activeQry = @"
SELECT SessionId
FROM UserSessions
WHERE UserSrno=@uid AND IsActive=1
ORDER BY LastActivity";

SqlParameter[] pActive =
{
    new SqlParameter("@uid", userSrno)
};

DataTable dtActive =
    SqlHelper.ExecuteDataset(con, CommandType.Text, activeQry, pActive)
    .Tables[0];

// Kill oldest session if limit reached
if (dtActive.Rows.Count >= maxSession)
{
    Guid oldSessionId =
        Guid.Parse(dtActive.Rows[0]["SessionId"].ToString());

    SqlParameter[] pKill =
    {
        new SqlParameter("@sid", oldSessionId)
    };

    SqlHelper.ExecuteNonQuery(
        con,
        CommandType.Text,
        "UPDATE UserSessions SET IsActive=0 WHERE SessionId=@sid",
        pKill);
}

// Create new session
Guid newSessionId = Guid.NewGuid();

SqlParameter[] pInsert =
{
    new SqlParameter("@sid", newSessionId),
    new SqlParameter("@uid", userSrno)
};

SqlHelper.ExecuteNonQuery(
    con,
    CommandType.Text,
    @"INSERT INTO UserSessions
      VALUES (@sid,@uid,GETDATE(),GETDATE(),1)",
    pInsert);

// Store session
Session["UserSrno"] = userSrno;
Session["SessionId"] = newSessionId;

Response.Redirect("Dashboard.aspx");

Session Activity Update (BasePage Concept)

protected void Page_Load(object sender, EventArgs e)
{
    if (Session["SessionId"] != null)
    {
        SqlParameter[] p =
        {
            new SqlParameter("@sid", Session["SessionId"])
        };

        SqlHelper.ExecuteNonQuery(
            con,
            CommandType.Text,
            @"UPDATE UserSessions
              SET LastActivity=GETDATE()
              WHERE SessionId=@sid AND IsActive=1",
            p);
    }
}

Auto-Expire Inactive Sessions (SQL Job)

UPDATE UserSessions
SET IsActive = 0
WHERE IsActive = 1
AND DATEDIFF(MINUTE, LastActivity, GETDATE()) > 30;

Purpose

  • Handles browser crash

  • Cleans unused sessions

  • Keeps session count accurate

Output Explanation

Scenario 1

User allowed 3 sessions, logs in 3 times
All logins allowed

Scenario 2

User logs in 4th time

  • Oldest session is terminated automatically

  • New session is created

  • Login succeeds

Scenario 3

User closes browser without logout

  • Session becomes inactive after timeout

  • Slot is freed for new login

Advantages of This Approach
  • Secure

  • Scalable

  • Works across devices

  • Handles unexpected logouts

  • Professional enterprise-ready solution

Conclusion

Concurrent login control is a critical security feature in modern applications.
By using a database-driven session tracking mechanism with GUID-based session IDs and LRU session termination, we can efficiently control active logins without impacting user experience.

This solution is simple, clean, and production-ready for ASP.NET WebForms applications.

 

Best ASP.NET Core 10.0 Hosting Recommendation

One of the most important things when choosing a good ASP.NET Core 8.0.11 hosting is the feature and reliability. HostForLIFE is the leading provider of Windows hosting and affordable ASP.NET Core, their servers are optimized for PHP web applications. The performance and the uptime of the hosting service are excellent and the features of the web hosting plan are even greater than what many hosting providers ask you to pay for. 

At HostForLIFE.eu, customers can also experience fast ASP.NET Core hosting. The company invested a lot of money to ensure the best and fastest performance of the datacenters, servers, network and other facilities. Its datacenters are equipped with the top equipments like cooling system, fire detection, high speed Internet connection, and so on. That is why HostForLIFEASP.NET guarantees 99.9% uptime for ASP.NET Core. And the engineers do regular maintenance and monitoring works to assure its Orchard hosting are security and always up.

0 comments:

Post a Comment