How to implement session that tied with user login in struts2? - session

I have this application flow with struts2:
Page_A.jsp contain form that can submit a data to ActionA class with method executeA
ActionA->executeA method stores data in a sesion with key "myKey"
ActionA return result to Page_B.jsp
Page_B.jsp contains form that can submit a data to ActionA class with method executeB
In ActionA->executeB method, it will get the submitted data from the "myKey" session
I found out there are two ways to set and get the data from session:
Using ActionContext
// put the data into session
Map session = ActionContext.getContext().getSession();
session.put("myKey", data);
// get the data from session
Map session = ActionContext.getContext().getSession();
data = (String[]) session.get("myKey");
Using ServletActionContext
// put the data into session
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession(false);
session.setAttribute("myKey", data);
// get the data from session
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = request.getSession(false);
data = (String[]) session.getAttribute("myKey");
Between the two ways, which one is the better way? Or is there an alternative better way? (I prefer the simple way if there is)
Second thing, I want to make sure the session is tied with user login session. That means "myKey" session data for one user will be different from "myKey" session data from another user (the "myKey" session data will never get overwritten by "myKey" session data from another user).
For example:
User1 login
User1 goes to Page_A.jsp and submit the data and now he's in Page_B.jsp (now the "myKey" session contains data submitted by User1)
User2 login
User2 goes to Page_A.jsp and submit the data too
I'm worried if User1 do submit from Page_B.jsp, will the data from "myKey" still refer to original data that he submitted or he will get the data from User2 (because the "myKey" session data was replaced) ?

Use ActionContext.getContext().getSession(); if you are working in an interceptor because it does not have the DI the actions have, for an action on the other hand add the SessionAware interface and the session will be injected.
The injection method lowers coupling and makes it easier to test your actions.
Both the above assume you don't need the full HttpServletRequest interface (which has far more functionality than just as map of parameters): http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html
Should you need this interface then ServletActionContext.getRequest(); is of course correct. Once again in the action you can lower coupling by using ServletRequestAware which will inject HttpServletRequest for you.
If you only need a property map then just use the methods which provide you with a map. Again this is because it's a lot easier to test and the intention is clear.
Sessions are unique, and they are maintained by the application server. For simplicity, when a user is using your application you can rest assured that there is a session.

Related

Getting session uuid set in redis

I am setting a session attribute whenever a user is logged in like this request.getSession().setAttribute(sessionUuid, user);. sessionUuid is uuid which I am setting. But seems like this sessionUuid is not the session id, redis generates a session id by itself. Which looks like something like this
1) "spring:session:expirations:1597563240000"
2) "spring:session:sessions:expires:9dfef52d-d94a-4bcf-a08e-4a362b36f332"
3) "spring:session:sessions:9dfef52d-d94a-4bcf-a08e-4a362b36f332"
From my understanding the session uuid is 9dfef52d-d94a-4bcf-a08e-4a362b36f332, for the attribute I have set.
What I am trying to understand is since redis generates a session id by itslef, then how am I supposed to get the redis session id, so that next time whenever user makes a request I can validate if the session is active or not ?
if(request.getSession().getAttribute("9dfef52d-d94a-4bcf-a08e-4a362b36f332") != null) {
return (UserSessionComponent) request.getSession().getAttribute(session);
}
Or does the redis search all the session for that particular attribute ?
Ok, I think I got it by experimenting. So for the SO readers we create a new session using this HttpSession newSession = request.getSession(true);, this will return a session or else it will create a new session if it doesn't exist.
And the HttpServletRequest will have the session whenever a user is making request or it may not have the session for the first time. This request.getRequestedSessionId() will give the same session uuid which is set on redis server, in this case it is 9dfef52d-d94a-4bcf-a08e-4a362b36f332 or else it will be null if it's first time.
Then using request.getSession().getAttribute(session); if it return null that means the session has been expired or else this will return the value.
By the way this is a good read on spring session

Strategy for logging Tomcat expired sessions

My web application logs user logins and logouts on a database table, so that we keep track of user activity.
This works well when users explicitly login or logout, since the underlying authentication code is responsible for these logging events.
However, when the user leaves the computer idle for 30 minutes, the web session will expire and we'll have one Login event without the corresponding Logout event.
The only strategy I've thought for resolving this is to have a javascript event that triggers before the 30 minutes defined in the web.xml and that kicks the user out before the session expires. However, that has the limitation of needing javascript, and when someone uses multiple tabs it can have some unexpected results (i.e., user is using tab2 and session is expired in tab1).
What would you suggest for this case?
You want to use an HttpSessionListener. It's a standard interface defined by the Servlet Specification for exactly this kind of situation.
See below for a caveat.
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class LogoutListener implements HttpSessionListener {
#Override
public void sessionDestroyed(HttpSessionEvent event) {
HttpSession session = event.getSession();
// NOTE: You need to store some kind of user identification
// in the session. My example just has a "username"
// in here.
String username = session.getAttribute("username");
// If the username is null, there was no logged-in user
// to log-out (e.g. non-authenticated user).
if(null != username) {
// NOTE: Obviously, this needs to call your existing
// "logout"-recording code. Just an example.
MyDBUtilities.registerLogout(username, System.currentTimeMillis());
}
}
#Override
public void sessionCreated(HttpSessionEvent event) {
// Ignore
}
}
If you use the code above, you'll find that users who don't explicitly log out will get a single logout record, and users who do explicitly log out will get two. Why? Because you are likely using your "logout" action to write the "logout" record and then the session listener runs immediately afterward and makes a second audit entry.
There are two obvious solutions to this problem:
Stop recording the logout event in your "logout" action, and let the event handler log all logouts
Remove the user's "username" session attribute when you log them out and the event handler will ignore the event
use a session listener to update the database when the session expires.
This is a simple example of how to implement session.
https://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/

Meteor Session Replacement?

In the latest Meteor release (version 0.5.8), Session has been removed from the server-side code.
Previously I've used Session to store client-specific variables for the server; what is the replacement for this functionality?
Example case: User One opens a browser, User Two opens a browser. One calls a method on the server setting some token, the other calls a method on the server doing the same. I then need to access this when the client requests something. How do I differentiate between the two?
You'll want to save your tokens to a collection in the database.
You could use a Session on the server if you wanted to simply by copying the session package into your application's packages directory and changing its package.js to also load on the server. But a Session is an in-memory data structure, and so won't work if you have multiple server instances; and you wouldn't be able to restart the server without losing your user's tokens.
If you store your tokens in the database they'll persist across server restarts, and will work with a future version of Meteor which is able to scale an application by adding more server instances when needed.
If you need to expire your tokens (so that your collection doesn't grow without bound), you could add a "lastUsed" Date field to your token collection, and periodically remove tokens that haven't been used for longer than your chosen expiration period.
You can use each one's session id which is unique to the tab too. Not too sure how to get the current session id but it should be there somewhere (you can see it in Meteor.default_server.sessions, so there is still a way:
Client js
Meteor.call("test", Meteor.default_connection._lastSessionId, function(err,result) {
console.log(result);
});
Server side Js
Session = {
set : function(key, value, sessionid) {
console.log(Meteor.default_server.sessions[sessionid]);
if(!Meteor.default_server.sessions[sessionid].session_hash) Meteor.default_server.sessions[sessionid].session_hash = {};
Meteor.default_server.sessions[sessionid].session_hash.key = value;
},
get : function(key, sessionid) {
if(Meteor.default_server.sessions[sessionid].session_hash)
return Meteor.default_server.sessions[sessionid].session_hash.key;
},
equals: function(key, value, sessionid) {
return (this.get(key, sessionid) == value)
},
listAllSessionids: function() {
return _.pluck(Meteor.default_server.sessions, "id");
}
};
Meteor.methods({
test:function(sessionid) {
if(!Session.get("initial_load", sessionid)) Session.set("initial_load", new Date().getTime(), sessionid);
return Session.get("initial_load", sessionid);
}
});
I hook into Meteor.default_connection._sessions to store the values so that theres some type of garbage collection involved when the session isn't valid anymore (i.e the user has closed his tabs) to prevent memory being wasted. In livedata_server.js these old sessions get destroyed after 1 minute of no activity on the DDP wire (like the heartbeat).
Because the server can see everyone's session you can use the sessionid to access another user's session data. and listAllSessionids to give out an array of all the sessionids currently active.
Automatically set session like this.userId in a Method without using a param in a call
It looks like there is functionality for this this but its not fully hooked up. The session id would be stored in this.sessionData but its likely still unfinished. Its there to be called in method but theres nowhere that its being set yet (in livedata_connection.js & livedata_server.js)

Session Variables Not Working

I am having a problem with my application. I am creating two session variables on a button click event, and then re-directing to another page and executing a method that selects data from a database (using the two session variables as parameters), and then displaying the results in a grid.
All works fine until I have two users (or more), who access the application, set their own session values, execute the data retrieval method, and of course they expect to see their own data.
What ends up occurring, is that both users see the same data, not their own specific data. Essentially, User A sees his data fine, but User B ends up seeing User A's data - not his own.
Note: this only occurs when they attempt to access their specific data 20 seconds apart
Here is my code sample:
//The user control that sets the session variables and redirects
Session.Clear();
Session.["ID"] = TxtPatientIDCode.Text.ToString());
Session["DOB"] = Convert.ToDateTime(TxtDateOfBirth.SelectedDate.Value.ToShortDateString());
Response.Redirect("mypage");
// the user control that gets the session variable values and executes //the data method
if (Session["ID"].ToString() != null)
{
SelectData();
}
Ammended
This is what occurs on the SelectData() method:
private void SelectData()
{
DataSet ds = Data.GetData(Session["ID"].ToString(),Session["DOB"].ToString());
gv.DataSource = ds;
gv.DataBind();
}
Also I did log this to a database table and it is inserting just fine, as it shows who and what times the data is accessed, as well as the session values that are being used.
Thanks again for the help
technooblet

HttpContext.Current.Session is Confused in Asp.net MVC 3.0

I'm working with an ASP.net MVC3.0 application and I keep Current User information in the Session of Current HttpContext.
As I know HttpContext.Current is for per current request.Therefore, my Session data should clear after the new request.However, I can receive Current User session data from request to request by storing HttpContext.Current. I did this sample for testing purpose to understand the session management in MVC 3.0.
My question: How I receive session data after current request ? I really appreciate your help.
public static UserAccountDto CurrentUser
{
get
{
if (HttpContext.Current == null)
return null;
if (HttpContext.Current.Session[CurrentUserSessionVariable] != null)
return HttpContext.Current.Session[CurrentUserSessionVariable] as UserAccountDto;
return null;
}
private set { HttpContext.Current.Session[CurrentUserSessionVariable] = value; }
}
HttpContext.Current is not the same as:
HttpContext.Current.Request
the last one is different at every request, the first one contains members like User, Session, Server etc that are in many (but not all) cases the same request after request.
what you have done is correct the session variable you have create will be available for all the request following the one that creates it.
The HttpContext is one of the largest object you will find in web development and behind the scene is does lots of stuff. The reason why you don’t lose the session between the requests is because the server will keep it alive. You will be surprised to know that behind the scene the session uses the particular section of the cache

Resources