I'm using the java servlet API in tomcat.
I save in a hash table the username and the httpsession with the attribute username and I would like to know if there is a way to check if the httpsession is valid.
I've tried:
try {
String user = httpSession.getAttribute("username")
return "is valid";
} catch (IllegalStateException e) {
return "is not valid";
}
What can I do if I don't want that a "logged" user connect from more than one place? If I control only if I create a new session, I can't know if he was connected already with another session.
No need to store the httpSession in your own hash.
Look at the API for the HttpServletRequest. If you look at method getSession(Boolean x) (pass false so it doesn't create a new session) will determine if the session is valid.
Here is an example
public void doGet(HttpServletRequest req, HttpServletResponse res) {
HttpSession session = req.getSession(false);
if (session == null) {
//valid session doesn't exist
//do something like send the user to a login screen
}
if (session.getAttribute("username") == null) {
//no username in session
//user probably hasn't logged in properly
}
//now let's pretend to log the user out for good measure
session.invalidate();
}
On a side note, If I read your question properly and you are storing the information in your own map, you need to be careful that you don't create a memory leak and are clearing the entries out of the hash table yourself.
I agree with Sean. I will add that a good practice for this type of checking is to use a Filter
See here Servlet Filter
Just take the code Sean have written and put it in a Filter instead. Define you filter in the web.xml and every time a request come in, the filter will execute.
This way you can validate if the user is auth. without cluttering your servlet code.
Rather than checking if a saved session is valid, you should be looking at the HttpServletRequest on your servlet, and checking isRequestedSessionIdValid() on that. When working in servlets you can always get Session from the Request, rather than saving it to a hash table.
Related
I have an action named "Login.action" that puts a certain type of object in the SESSION but depending on this object i want to do something with jQuery this is my example
public String execute() {
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession sesion = request.getSession();
sesion.setAttribute(user.getprofile(), user);
return SUCCESS;
}
as i said i put an object in my SESSION so i want to acces later on JSP with jQuery
(if the user's profile is "Admin" i want to make an "Admin Panel" button appear using jQuery)
Also i want to know if this is a good way to get this result or there's another (and better) way to do it
Strut set session
Map session = ActionContext.getContext().getSession();
session.put("user","username);
set your user in session
$.session.set("user", $("#uname").val());
get session user
$.session.get('user');
This question already has answers here:
How do servlets work? Instantiation, sessions, shared variables and multithreading
(8 answers)
Closed 7 years ago.
I am new to Java EE. I have a site which requires a user to log in, and after the user logs in I would like the user to see his/her own item (e.g: shopping cart).
So that means I have to use a session to accomplish that. But how do I deal with multiple sessions?
For example multiple users login to the system as well as to the same servlet? However, can I keep multiple sessions in one servlet? Do I keep a record of each of them? How does it work?
Can someone give an example please ?
In servlet you have access to HttpServletRequest which provides you with a getSession() method. This methods returns session object (essentialy a key-value map), different for each user.
If you put something into that map (like shopping cart), you can retrieve it later - but only when the same user accesses the application again (not necessarily the same servlet).
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
HttpSession session = request.getSession();
session.getAttribute("cart");
//...
session.setAttribute("cart", whateverYouWant);
Sessions are maintained in the servlet container and looked up by session id (typically a cookie). You don't have to implement anything yourself.
Yes you can. The servlet container will keep track of them for you, so you shouldn't have to do that bookkeeping yourself. The Session object can be obtained from the HttpServletRequest in your servlet code. Since your code only has to concern itself with a single request at a time, there's generally not much pain in dealing with multiple sessions.
To deal with multiple users login in Servlets, create a session for each login as
HttpSession session = request.getSession();
public HttpSession getSession()
returns the current session associated with this request, or if the request does not have a session, creates one.
Each session will identify the users uniquely.
Now if user wants to change some data that is in database then after creating session, set attribute with that session with the information which can uniquely identify the user in database, for e.g. email_id as:
session.setAttribute("id",email_id of user);
This attribute can be retrieved later in another Servlet/JSP as:
String email_id = session.getAttribute("id");
This attribute will help in identifying the user who has sent request to server to update data in database or to do something else.
For more methods related to the session, refer the link:
http://www.javatpoint.com/http-session-in-session-tracking
I have a task to show to the site admin a list of user names and how many tomcat sessions are currently utilized by each user (along with some other support-related information).
I keep authenticated users as the application context attribute as follows (sparing unnecessary details).
Hashtable<String, UserInfo> logins //maps login to UserInfo
where UserInfo is defined as
class UserInfo implements Serializable {
String login;
private transient Map<HttpSession, String> sessions =
Collections.synchronizedMap(
new WeakHashMap<HttpSession, String>() //maps session to sessionId
);
...
}
Each successful login stores the session into this sessions map.
My HttpSessionsListener implementation in sessionDestroyed() removes the destroyed session from this map and, if sessions.size() == 0, removes UserInfo from logins.
From time to time I have 0 sessions showing up for some users. Peer reviews and unit testing show that the code is correct. All sessions are serializable.
Is it possible that Tomcat offloads sessions from memory to the hard drive, e.g. when there is a period of inactivity (session timeout is set to 40 minutes)? Are there any other scenarios where sessions are 'lost' from GC point of view, but HttpSessionsListener.sessionDestroyed() wasn't invoked?
J2SE 6, Tomcat 6 or 7 standalone, behaviour is consistent on any OS.
As this question got close to 5k views, I think it would be beneficial to provide an example of a working solution.
The approach outlined in the question is wrong - it will not handle server restarts and will not scale. Here is a better approach.
First, your HttpServlet needs to handle user logins and logouts, something along these lines:
public class ExampleServlet extends HttpServlet {
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String action = req.getParameter("do");
HttpSession session = req.getSession(true);
//simple plug. Use your own controller here.
switch (action) {
case "logout":
session.removeAttribute("user");
break;
case "login":
User u = new User(session.getId(), req.getParameter("login"));
//store user on the session
session.setAttribute("user",u);
break;
}
}
}
The User bean has to be Serializable and has to re-register itself upon de-serialization:
class User implements Serializable {
private String sessionId;
private String login;
User(String sessionId, String login) {
this.sessionId = sessionId;
this.login = login;
}
public String getLogin() { return login; }
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
//re-register this user in sessions
UserAttributeListener.sessions.put(sessionId,this);
}
}
You will also need an HttpAttributeListener to handle session lifecycle properly:
public class UserAttributeListener implements HttpSessionAttributeListener {
static Map<String, User> sessions = new ConcurrentHashMap<>();
#Override
public void attributeAdded(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
sessions.put(event.getSession().getId(), (User) event.getValue());
}
#Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
ExampleServlet.sessions.remove(event.getSession().getId());
}
#Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if ("user".equals(event.getName()))
ExampleServlet.sessions.put(event.getSession().getId(),
(User)event.getValue());
}
}
Of course, you will need to register your listener in web.xml:
<listener>
<listener-class>com.example.servlet.UserAttributeListener</listener-class>
</listener>
After that, you can always access the static map in UserAttributeListener to get an idea of how many sessions are running, how many sessions each user is using etc. Ideally, you would have a bit more complex data structure warranting its own separate singleton class with proper access methods. Using containers with copy-on-write concurrent strategy might also be a good idea, depending on the use case.
Instead of writing something from scratch, check out psi-probe.
http://code.google.com/p/psi-probe/
This may just be a simple drop in that solves your problems.
Do you find that you get the issue following a restart of Tomcat? Tomcat will serialize active sessions to disk during a successful shutdown and then deserialize on startup - I'm not sure whether this will result in a call to your HttpSessionListener.sessionCreated() as the session isn't strictly created, just deserialized (this may be not be correct(!), but can be tested fairly easily).
Have you also compared your results with the Tomcat managers session stats? It keeps track of the number of active sessions, and should tie up with your figures, if not, you know your code is wrong.
Also, probably unrelated to your issue, but is there a good reason why you are using Hashtable and WeakHashMap? I tend to go with ConcurrentHashMap if i need a thread safe Map implementation, its performance is much better.
When a client visits the webapp for the first time and/or the HttpSession is obtained for the first time via request.getSession(), the servlet container creates a new HttpSession object, generates a long and unique ID (which you can get by session.getId()), and store it in the server's memory. The servlet container also sets a Cookie in the Set-Cookie header of the HTTP response with JSESSIONID as its name and the unique session ID as its value.
As per the HTTP cookie specification (a contract a decent web browser and web server have to adhere to), the client (the web browser) is required to send this cookie back in subsequent requests in the Cookie header for as long as the cookie is valid (i.e. the unique ID must refer to an unexpired session and the domain and path are correct). Using your browser's built-in HTTP traffic monitor, you can verify that the cookie is valid (press F12 in Chrome / Firefox 23+ / IE9+, and check the Net/Network tab). The servlet container will check the Cookie header of every incoming HTTP request for the presence of the cookie with the name JSESSIONID and use its value (the session ID) to get the associated HttpSession from server's memory.
The HttpSession stays alive until it has not been used for more than the timeout value specified in <session-timeout>, a setting in web.xml. The timeout value defaults to 30 minutes. So, when the client doesn't visit the web app for longer than the time specified, the servlet container trashes the session. Every subsequent request, even with the cookie specified, will not have access to the same session anymore; the servlet container will create a new session.
On the client side, the session cookie stays alive for as long as the browser instance is running. So, if the client closes the browser instance (all tabs/windows), then the session is trashed on the client's side. In a new browser instance, the cookie associated with the session wouldn't exist, so it would no longer be sent. This causes an entirely new HTTPSession to be created, with an entirely new session cookie begin used.
I want to store the the user's ID in a session variable to use across the application. I don't see how I'd do that with the default security feature? It authenticates itself and I don't know (if) there is a callback function or something? That we can use to do our house-keeping
Any help is deeply appreciated
You can use a Filter for this which checks if the user is logged in by container managed security (i.e. HttpServletRequest#getUserPrincipal() doesn't return null) and then sets the session variable if not present.
Basically:
if (request.getUserPrincipal() != null && session.getAttribute("user") == null) {
session.setAttribute("userId", userId);
}
However, maybe you don't need to do it at all since it proves that you aren't aware about HttpServletRequest#getUserPrincipal(). It may namely already offer exactly the information you need. The login username (it may be the same as the user ID where you're talking about) is available by Principal#getName().
This question already has answers here:
How do servlets work? Instantiation, sessions, shared variables and multithreading
(8 answers)
Closed 5 years ago.
So far I understand Httpsession concepts in Java.
HttpSession ses = req.getSession(true);
will create a session object, according to the request.
setAttribute("String", object);
will, bind the 'String', and value with the Session object.
getAttribute("String");
will return an object associated with the string, specified.
What I am not able to understand is: I am creating a session object like
HttpSession ses = req.getSession(true);
and setting a name for it by calling setAttribute("String", object);.
Here, This code resides inside the server. For every person, when he tries to login the same code in the server will be executed. setAttribute("String", object); in this method the string value is a constant one. So, each session object created will be binded by the same string which I have provided. When I try to retrieve the string to validate his session or while logout action taken the getAttribute("String"); ll return the same constant string value(Am I right!!?? Actually I don't know, I'm just thinking of its logic of execution). Then, how can I be able to invalidate.
I saw this type of illustration in all of the tutorials on the WEB. Is it the actual way to set that attribute? Or, real application developers will give a variable in the "String" field to set it dynamically
(ie. session.setAttribut(userName, userName); //Setting the String Dynamically.. I dono is it right or not.)
And my final question is
WebContext ctx = WebContextFactory.get();
request = ctx.getHttpServletRequest();
What do the two lines above do? What will be stored in ctx & request?
HttpSession ses = req.getSession(true); will creates new session means. What value stored in ses.
Some [random] precisions:
You don't need login/logout mechanisms in order to have sessions.
In java servlets, HTTP sessions are tracked using two mechanisms, HTTP cookie (the most commonly used) or URL rewriting (to support browsers without cookies or with cookies disabled). Using only cookies is simple, you don't have to do anything special. For URL re-writing, you need to modify all URLs pointing back to your servlets/filters.
Each time you call request.getSession(true), the HttpRequest object will be inspected in order to find a session ID encoded either in a cookie OR/AND in the URL path parameter (what's following a semi-colon). If the session ID cannot be found, a new session will be created by the servlet container (i.e. the server).
The session ID is added to the response as a Cookie. If you want to support URL re-writing also, the links in your HTML documents should be modified using the response.encodeURL() method. Calling request.getSession(false) or simply request.getSession() will return null in the event the session ID is not found or the session ID refers to an invalid session.
There is a single HTTP session by visit, as Java session cookies are not stored permanently in the browser. So sessions object are not shared between clients. Each user has his own private session.
Sessions are destroyed automatically if not used for a given time. The time-out value can be configured in the web.xml file.
A given session can be explicitly invalidated using the invalidate() method.
When people are talking about JSESSIONID, they are referring to the standard name of the HTTP cookie used to do session-tracking in Java.
I suggest you read a tutorial on Java sessions. Each user gets a different HttpSession object, based on a JSESSIONID request/response parameter that the Java web server sends to the browser. So every user can have an attribute with the same name, and the value stored for this attribute will be different for all users.
Also, WebContextFactory and WebContext are DWR classes that provide an easy way to get the servlet parameters.
As I understand it, your concerns are about separation of the different users when storing things in the HttpSession.
The servlet container (for example Tomcat) takes care of this utilizing its JSESSIONID.
The story goes like this :
User first logs onto website.
Servlet container sets a COOKIE on
the user's browser, storing a UNIQUE
jsessionId.
Every time the user hits the
website, the JSESSIONID cookie is
sent back.
The servlet container uses this to
keep track of who is who.
Likewise, this is how it keeps track
of the separation of data. Every
user has their own bucket of
objects uniquely identified by the
JSESSIONID.
Hopefully that (at least partially) answers your question.
Cheers
Your basic servlet is going to look like
public class MyServlet{
public doGet(HttpServletRequest req, HttpServletResponse res){
//Parameter true:
// create session if one does not exist. session should never be null
//Parameter false:
// return null if there is no session, used on pages where you want to
// force a user to already have a session or be logged in
//only need to use one of the two getSession() options here.
//Just showing both for this test
HttpSession sess = req.getSession(true);
HttpSession sess2 = req.getSession(false);
//set an Attribute in the request. This can be used to pass new values
//to a forward or to a JSP
req.setAttribute("myVar", "Hello World");
}
}
There is no need to set any attribute names for your session that is already done. As others have suggested in other answers, use cookies or URL re-writing to store the sessionID for you.
When you are dealing with the DWR WebContext, it is simply doing the same thing as above, just normally the Request object isn't passed into the method, so you use the WebContext to get that request for you
public class DWRClass {
public doSomething(){
WebContext ctx = WebContextFactory.get();
HttpServletRequest req = ctx.getHttpServletRequest();
HttpSession sess = req.getSession(); //no parameter is the same as passing true
//Lets set another attribute for a forward or JSP to use
ArrayList<Boolean> flags = new ArrayList<Boolean>();
req.setAttribute("listOfNames", flags);
}
}