I’ve been working on a subscription site, logins are powered by the ASP.net membership provider system.
Now I want to stop people sharing their logins and avoiding paying for a subscription. We don’t really want multiple logins from the same username.
After a lot of Googling I came up with an almost suitable solution:
http://www.eggheadcafe.com/articles/20030418.asp
The only problem for me is that this solution stops a new login. This means that if a user logs in, closes the browser, and then logs in again, they are denied a login for the next twenty minutes (or however long the session timeout is set to).
So I switched things around, and actually ended up with a slightly simpler solution.
In my asp:Login control’s LoggedOn event I have the following:
protected void LoginMain_LoggedIn(object sender, EventArgs e)
{
System.Web.UI.WebControls.Login senderLogin = sender as System.Web.UI.WebControls.Login;string key = senderLogin.UserName + senderLogin.Password;
TimeSpan TimeOut = new TimeSpan(0, 0, HttpContext.Current.Session.Timeout, 0, 0);
HttpContext.Current.Cache.Insert(key,
Session.SessionID,
null,
DateTime.MaxValue,
TimeOut,
System.Web.Caching.CacheItemPriority.NotRemovable,
null);Session["username"] = key;
}
We concatonate the username and password as before and use this as the key for a cache item. The cache item value though is set to the just logged in users SessionID. We then add the key to a session variable.
In global.asax we have:
protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
if (HttpContext.Current.Session != null)
{
if (Session["username"] != null)
{
string cacheKey = Session["username"].ToString();
if ((string)HttpContext.Current.Cache[cacheKey] != Session.SessionID)
{
FormsAuthentication.SignOut();
Session.Abandon();
Response.Redirect("/errors/DuplicateLogin.aspx");
}string user = (string)HttpContext.Current.Cache[cacheKey];
}
}
}
This will fire for every request. If the username session variable exists then the SessionID is taken from the cache and compared to the current SessionID. If they don’t match then the user is kicked to an error page after being logged out and Session.Abandoned.
This means that a second user logging in will change the cached SessionID and login fine, whilst the original user will be logged out.
The error message explains what has happened and provides support for what to do. Which is of course either, stop cheating me out of cash, or let us know if you think your account is compromised.


March 2nd, 2010 at 7:56 pm
Great tip, thanks.
March 15th, 2010 at 7:27 pm
This is the most practical solution to this quite complex problem
June 26th, 2010 at 2:07 pm
Very very cool tip. thanks.
December 7th, 2010 at 10:59 am
Is there anything to do in the Web.config with this solution.
December 7th, 2010 at 10:59 am
Is there anything to do in the Web.config or anything else to do with this solution ? Thanks.
December 7th, 2010 at 11:37 am
It’s already done.
Thanks so much !!
December 7th, 2010 at 11:38 am
Excellent news. Glad I could help
October 24th, 2011 at 9:23 am
Will u Plz send the whole code
thanks and regards
annapurna
April 20th, 2012 at 3:39 pm
I’m a bit late to the party here, but was just wondering why you included the password in the Session key?
Wouldn’t it be sufficient just to use the username, and be a little more secure not to use the password in this way?
Steve
April 20th, 2012 at 3:48 pm
You know what Steve, I can’t rightly remember and I can’t think of a good reason why when thinking of it afresh. Good point.