1

I'm developing a Java based backend and I'm having troubles while managing my user sessions.

I would like to store some personal information for each user in the session, hence I implemented a Servlet for login purpose which creates a session if the login is successful:

    @WebServlet("/LoginUserWithPassword")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, // 2MB
maxFileSize = 1024 * 1024 * 10, // 10MB
maxRequestSize = 1024 * 1024 * 50) // 50MB
public class LoginUserWithPassword extends HttpServlet {
    private static final long serialVersionUID = 1L;
    static Logger log = Logger.getLogger(LoginUserWithPassword.class);


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");


....
        HttpSession session = request.getSession();
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("nom",usr.nom);
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("prenom", usr.prenom);
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("login", usr.email);
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("id", String.valueOf(usr.id_user));
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("id_right",String.valueOf(ur.id_right));
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("right",url.right);
        session.getServletContext().getContext("/{applicationContextRoot}").setAttribute("session",session.getId());

then, on the client side (JSP/Javascript), I'm retrieving the session information.

Considering a user1, who is logging successfully on a browser (Chrome) with the following Javascript code:

Glogin = '<%= (String) (request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute("login")) %>';
        Gsession = '<%= (String) (request.getSession().getServletContext().getContext("/{applicationContextRoot}").getAttribute("session")) %>';

        console.log("login from session: "+Glogin);
        console.log("Session ID: "+Gsession);

I can see the following console logs:

login from session: admin3@toto.com
Session ID: 7D6638EA7167580F4C1BD4D51FAD3C9C

Then I'm performing a second login of user2 on the same computer with another browser (FF), I have the following in the console logs:

login from session: admin@toto.com
Session ID: 376C57F6ACB08CD3B66AB8406DB72984

at that stage everything is perfect, I can retrieve my respective attributes on each session,but If I refresh the browser of user1, I retrieve the session ID of user 2....and lose my user1 session context.

Do you have an idea why I'm getting such behavior ? may be my way of implementing session management is not correct ?

tiamat
  • 879
  • 2
  • 12
  • 35

2 Answers2

1

You are not using the session correctly. Replace session.getServletContext().getContext("/{applicationContextRoot}") with session everywhere. The servlet context is global (shared).

ewramner
  • 5,810
  • 2
  • 17
  • 33
  • yes I know but it was the only solution I found to handle session sharing between two independent war files (on the same tomcat instance), do you have any other solution ? – tiamat May 24 '18 at 20:58
  • Yes indeed. See https://stackoverflow.com/questions/9436736/sharing-session-data-between-contexts-in-tomcat. Add / to your web.xml or use one of the other methods mentioned in the same answer. – ewramner May 25 '18 at 06:11
  • This is exactly what I did in my context.xml, it gives me the possibility to share sessions between war, but I had to use getServletContext instead of session directly to retrieve my Session on my JSP page...the only drawback is the fact that the session is shared and is not storing one session per user – tiamat May 25 '18 at 07:17
  • Right. I think you will run into problems with this down the line. The deployments are not really independent. If they share objects and you redeploy one application there may be memory leaks as old classes are still referenced from live objects, for example. Plus you won't be able to scale by moving some war files to another server if they depend on communicating within the same JVM. I would either recommend a single deployment unit or moving to a full distributed session implementation, for example Spring Session with a Redis backend. Anyway, good luck! – ewramner May 25 '18 at 07:41
  • I think you're right, I'll have for sure other troubles so I'll come back to a more "standard" implementation... – tiamat May 26 '18 at 10:41
1

Dont put it in ServletContext, it will override the previous values. Instead put it in the current session like given below:

request.getSession().setAttribute("nom",usr.nom);

And retrieve these values on JSP from session like

(String)session.getAttribute("nom");

[Edit]

Currently you are following architecture like

Browser(CLient) ---> Calling JSP on War 1 -----> Calling Servlet on war 2

You can maintain session between Browser(Client) ----> Calling JSP on war 1

When you authenticate your user the details of Users from war 2, the details of users can be captured in as pipe symbol separated in a string that String can be saved in ServletContext (Note perform this code in war 2 only)

    Map<String. String> allUsers = new HashMap<>();
// add key as user id and value is comma separated in string
    ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
    servletContext.setAttribute("users",allUsers );

Your servlet should return user id to JSP in response

war 2 ----> returning user id to JSP in war 1

Now you should save this user id in the session that you are maintaining between Browser (CLient) -----> JSP on war 1.

Whenever you want to use values that you had stored in war 2 in servlet context, you can use below code in JSP in war 1

ServletContext servletContext =request.getSession().getServletContext().getContext("contextPath")
servletContext.getAttribute("user"); 

Note : You can not share session between two war files however you can share objects between them.

May this will help you.

Vaibhav Sharma
  • 1,573
  • 2
  • 19
  • 35
  • yes but I deployed my frontend and my backend in two independent war files (on the same tomcat instance) and the only solution I found to manage a session shared between my two war files was by using ServletContext....If I'm using only session I'm not able to share it. any other solution ? – tiamat May 24 '18 at 20:26
  • Why are you having frontend (JSP) and backend (Servlet) in two different war file. As JSP gets converted into servlet after compilation you should have JSPs and Servlets in your same war file. And how is it possible that your JSP form submission is calling a servlet which resides in different war file. Are you using full URL in form submission – Vaibhav Sharma May 24 '18 at 20:33
  • I'm having different frontends (JSP+JS) with different look and feel and functionalities relying on the same backend....but this is true I'm facing troubles with session sharing.... – tiamat May 24 '18 at 20:38
  • I have provided answer with Edit tag, may this will help you – Vaibhav Sharma May 24 '18 at 21:05
  • this could be a good solution, I'll implement it and will let you know. – tiamat May 24 '18 at 21:07
  • If possible change your architecture, you may face architecture problem at multiple locations. – Vaibhav Sharma May 24 '18 at 21:11
  • yes but this architecture is providing more deployment flexibility....having only one single war file containing multiple front end could be difficult to maintain and deploy – tiamat May 24 '18 at 21:12