Link to home
Create AccountLog in
Java

Java

--

Questions

--

Followers

Top Experts

Avatar of mchicken
mchicken

How do I check duplicate login using servlet?
Dear all,

I have a marking system which would limit only one login per account. i.e. When a user once login the system, it don't have permission to login to the system again using the same user/password unless he has logout the system.

I think the mechanism is to store all the user name to an object. Then check whether the user name has already existed in that object or not.

The problem is I don't have idea on how to implement it. Can anyone give me suggestion?

Thx

Zero AI Policy

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Avatar of CEHJCEHJ🇬🇧

You could do this with a LoginManager class that owned a Map of Login objects, keyed on username. If the username is found in the Map, the user gets told they're already logged in; otherwise a new Login objects is created and saved in the Map.

Avatar of mchickenmchicken

ASKER

Any sample for the LoginManager?

ASKER CERTIFIED SOLUTION
Avatar of CEHJCEHJ🇬🇧

Link to home
membership
Log in or create a free account to see answer.
Signing up is free and takes 30 seconds. No credit card required.
Create Account

Seems what I want...

I got a problem.
If the user logout probably by clicking on the logout button, the username stored in the HashMap could be removed. However, if the session timeout automatically, the user is not able to logout probably. Later on, user could not able to login again since the username still on the HashMap. Any suggestion for this situation?

I think a way to do it but don't whether it's work or not. When user login, I store the session value to the HashMap. Each time check whether the session value still exist at the server. If not, then remove the login from the HashMap. But how to check whether the session value still exist at the server?

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


Avatar of CEHJCEHJ🇬🇧

What's the context of all this - a web server application?

Actually it's a online marking system for students and teachers to use. User could login to give marks for assignments.

I used Java servlet to develop it. For each login, a new session would be created. Now, it has to limit to only one login for each account.

I think LoginManager is somewhat meet my requirement. But it would has problem if the session was expired as the username still exist in the HashMap. That's what I described above.

Avatar of CEHJCEHJ🇬🇧

What concerns me is reinventing the wheel - some of this functionality that you're looking for here may already be in your container.

Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Actually it's a online marking system for students and teachers to use. User could login to give marks for assignments.

I used Java servlet to develop it. For each login, a new session would be created. Now, it has to limit to only one login for each account.

I think LoginManager is somewhat meet my requirement. But it would has problem if the session was expired as the username still exist in the HashMap. That's what I described above.

Above is a wrong reply.

I use tomcat v4.0.1. I don't find that it has such functionality.

Avatar of CEHJCEHJ🇬🇧

Make the Login object implement HttpSessionBindingEvent.
Then you could do something like:

if (logins.containsKey(username)){
  Login l = logins.get(username);
  if (!l.getUnbound()){
    System.err.println(username + " is already logged in - please log out first");
      return null;
  }
}

You'll have to rearrange the modifiers as:

public void valueUnbound(HttpSessionBindingEvent event)

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


Avatar of CEHJCEHJ🇬🇧

The other thing you'll have to watch is that there can be problems with the Singleton pattern in servlet engines. See this discussion:
https://www.experts-exchange.com/questions/20327891/Help-me-understand-static.html

Actualyl I think if I could check the existing for a session in the container, I could remove the username from the HashMap.

Anyway, let me try the HttpSessionBindingEvent that you suggested first.

Avatar of CEHJCEHJ🇬🇧

A more elegant solution would be to use a weak hash map. I use the last three words in the previous sentence advisedly
as a WeakHashMap is not appropriate as you  want to ensure that the referent is the Session reference, not the key. Still, if you are not familiar with this concept, you can begin by looking at these docs:


http://javaalmanac.com/egs/java.util/coll_WeakMap.html
http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html

Also have a look at the docs on WeakReference

N.B. You don't need 1.4 to do this.

Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Hi mchicken, :-)

maybe you could extend CEHJ's Login class with some more information:
- sessionID
- lastAccessTimestamp

Then, you could implement a custom Tag 'IfLoggedIn' which would be placed around all JSP code on each page of your web-app (usefull anyway so it is not possible to 'hack in' some page using URL). This Tag would get Login object from your user's session and compare their sessionID. If sessionID is the same, JSP body would be included, otherwise JSP body would be skipped. Additionally it would update lastAccessTimestamp.

Your login page would do a Login object lookup. If Login object is found and sessionID is different then you would check if last access timeout (defined by you) was reached, yes - allow login and update Login object in LoginManager with sessionID and lastAccessTimestamp, no - reject login.

Greetings
    </ntr> :)

p.s. If this works for you, don't forget to reward your points to CEHJ, for he provided you with the solution in the first place! :-)

Avatar of CEHJCEHJ🇬🇧

>>If this works for you, don't forget to reward your points to CEHJ

Very delicate Neutron - thank you!

The point about my last observations, just in case you've missed it by not being familiar with reference objects is that if you implement the above correctly, the hashed login will *automatically* be removed from the map when the session goes out of scope, so you don't need to do anything.

>Very delicate Neutron - thank you!
No problem, people sometimes can't distinguish between a clarification and a proposed solution:)

For this 'automatic' removal, I can see that you used HashMap which uses an array to hold references to Entry instances. These are ordinary strong references, right?

I thought that automatic removal works only for WeakHashMap?
...and even then removal is not automatic but WeakReference WeakKeys will only become candidates for the next garbage collection?

Greetings,
    </ntr> :)

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


Avatar of CEHJCEHJ🇬🇧

>>
I can see that you used HashMap which uses an array to hold references to Entry instances. These are ordinary strong references, right?
>>

Correct, but I'm now suggesting implementing a weak hash map instead.

>>
I thought that automatic removal works only for WeakHashMap?
>>

Correct. By the way, it's important for the questioner to realise that WeakHashMap is 1.4 only, but that doesn't stop him from implementing a weak hash map. Indeed if you see my earlier comment, this is probably necessary anyway.

>>and even then removal is not automatic but WeakReference WeakKeys will only become candidates for the next garbage collection

Well spotted neutron! I was going to mention this but didn't want to confuse the issue any further. This weakness might be mitigated however by various means. Thoughts?


>Correct. By the way, it's important for the questioner to realise that WeakHashMap is 1.4 only, but that doesn't
>stop him from implementing a weak hash map. Indeed if you see my earlier comment, this is probably necessary anyway.

Actually WeakHashMap it is there since 1.2

>>and even then removal is not automatic but WeakReference WeakKeys will only become candidates for the next garbage collection
>Well spotted neutron! I was going to mention this but didn't want to confuse the issue any further. This
>weakness might be mitigated however by various means.
>Thoughts?

You can always force garbage collection using
    System.gc();
    System.runFinalization();

...but I don't really know how wise it would be, since the same VM is used for Tomcat401. Maybe then mchicken would have some performance problems with webapps running on tomcat?

Btw, when we are talking about WeakHashMap (not strictly related to the question here), WeakHashMap is using HashMap internally to hold 'Values' of the Map, so only the 'Keys' are weak-referenced. The class does some sort of cleanup of this strong-reference Map whenever you do some operation which makes a modification of data in the Map (put, remove, clear).

This means that if you fill a WeakHashMap with a million objects and then you stop modifying it (just read), the keys will be reclaimed in time, but values will still be referenced by the WeakHashMap. I thought that at least WeakKey class (inside WeakHashMap) has some finalize() method which would do a reference cleanup.
Strange, or...?

Greetings,
    </ntr> :)

Many thx to CEHJ & Neutron for details description.

I think WeakHashMap would be helpful. For WeakHashMap, is it a must to manually cleanup the value for an invalid key?

1)I think I would put (session, username) into the WeakHashMap.

2)If the username still exist in the Map, user has already login.

3)If the cleanup is done manually, I would do it at every login.

Actually I have question in retrieving the existing session from the container.

Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


I have read the documentation given by CEHJ. I think it may have problem if the WeakReference is being automatically released.

As the session timeout is set at the container, it would be helpful if I could retrieve the sessionID from the container. So that I could lookup from the HashMap and see whether the session for a user has expired or not.

I think it would be easier to implement it.

Avatar of CEHJCEHJ🇬🇧

I'll have a think about this. One thing would be useful in this is to give me an idea of your anticipated application logic flow so it's clear in my mind. E.g:

1. User enters details in web form
2. Servlet contacts login manager to see if user already logged in.

etc.

The application logic is as follows:

1. Users' data are stored in database
2. User enter username/password in login.htm
3. LoginHandler.class would check username/password from database.
4. If matches, put(username, sessionID) into HashMap of Login Manager.
5. When user logout, remove(username, sessionID) from HashMap.
6. Repeat the steps 2-5 for next login / logout.

Since session would expire due to timeout, all expired session should be removed from HashMap. Or else user could not login forever after first login.

Thus I think all sessionID should be put into another HashMap (or if all the existing sessions could be checked from tomcat, then this HashMap is unnecessary). Put sessionID when new session is created and removed when session is destroyed.

Someone suggests to use HttpSessionListener and use its sessionCreated and sessionDestroyed methods. However, I don't know exactly how it works.

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.


I can monitor all the session being created and destroy using HttpSessionListener.

CEHJ,
Many thx for your solution using HashMap. I would accept it as answer. Thank you very much.

Avatar of CEHJCEHJ🇬🇧

OK thanks. I'd be interested in seeing your final result!

Following is the code to monitor and store a session when being created or destroy in the container:


import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

public class SessionCounter implements HttpSessionListener {
  private static int activeSessions = 0;
  private static Map sessionMap = new HashMap();
  static private SessionCounter instance;
     
  public static SessionCounter getInstance(){
    return instance == null? (instance = new SessionCounter()) : instance;
  }

  /* Session Creation Event */
  public void sessionCreated(HttpSessionEvent se) {
    sessionMap.put(se.getSession().getId(), se.getSession().getId());
    activeSessions++;
  }

  /* Session Invalidation Event */
  public void sessionDestroyed(HttpSessionEvent se) {
    if(activeSessions > 0){
      removeSessionHash(se.getSession().getId());
      activeSessions--;
    }
  }

  /* Get total count of existing session */
  public static int getActiveSessions() {
    return activeSessions;
  }

Free T-shirt

Get a FREE t-shirt when you ask your first question.

We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads.


Avatar of CEHJCEHJ🇬🇧

Looks fine. Personally, i would expect a method called 'getActiveSessions()' to return a collection of sessions, and would have used getActiveSessionCount() or something. Don't forget about managing the problem of Tomcat ignoring your carefully constructed singleton pattern implementation (see above)

All the existing sessions are stored in the HashMap. The above code is a simple one only. It works fine with my system until now.

Problem of Tomcat? I don't quite understand that. Could you explain further?

Avatar of CEHJCEHJ🇬🇧

As above:

>>
The other thing you'll have to watch is that there can be problems with the Singleton pattern in servlet engines. See this discussion:
https://www.experts-exchange.com/questions/20327891/Help-me-understand-static.html 
>>

the point being that if the wrong classloader loads a singleton, it can be loaded multiple times by other classloaders, thus completely ignoring the singleton. Follow the external links in the external link above.

Reward 1Reward 2Reward 3Reward 4Reward 5Reward 6

EARN REWARDS FOR ASKING, ANSWERING, AND MORE.

Earn free swag for participating on the platform.

Java

Java

--

Questions

--

Followers

Top Experts

Java is a platform-independent, object-oriented programming language and run-time environment, designed to have as few implementation dependencies as possible such that developers can write one set of code across all platforms using libraries. Most devices will not run Java natively, and require a run-time component to be installed in order to execute a Java program.