On the server side, after a successful logon, I execute :
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession();
session.setAttribute("user", subject.getUser().getId());
session.setAttribute("logged", true);
I then assume that the user is logged in. When the user navigates to a secure page in order to save or delete a record from my database, I run this code.
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession();
if (session.getAttribute("user")!=null && session.getAttribute("logged"))
{
//delete a record using the authority of the user.
}
My concern is that a client can tamper its browser cookie with a different user id. The database request would be initiated with a different user, skipping the login process.
Can java session identify tampering, or should I digitally sign the session by including this line
session.setAttribute("signature", hash(secretkey + subject.getUser().getId());
then verify that the signature is valid before changing the database.
if (session.getAttribute("signature").equals(hash(secretkey + session.getAttribute("user"))
{
//delete a record using the authority of the user.
}
Have you examined your cookies? Are you actually keeping the user-id in a cookie, and if yes, what for?
The server side session object can't be accessed from the client side, that would be a huge security problem.
If your code is correct, there's no reason or advantage in using a hash.
Related
Can we put authentication token in session object?
For example:
session.setAttribute("authToken",authTokne);
In my case I have to use authToken in every request call.
In service layer i am using third party services. In each request i need to pass authentication token. Getting authentication token is also a one request. I need to do many request calls step by step. At first request i am getting token and holding it in object level. After some time i need to make another request from different location(another class/object), now token is not available here. For this one more request i need to send for token. So avoiding this every time new call for a token, Can i put this token in servlet session varaible?
In term of security reasons is it good approach?
The all session data is kept on the server, so you can put anything you want there. The browser user is associated to the session via sessionId in a cookie (looked up by container upon request). When a user connects to server, a cookie is dropped on the browser with sessionId. Upon return the browser sends this sessionId back so you can lookup the session (usually a Map) to track data associated with the user and their current session. Session cookies can be set to persist through browser closing or expire when browser closes or after a certain time.
Storing the auth token in session is fine, but you will not be able to find a session based on auth token stored in it if the browser doesn't support or doesn't store cookies. If a user has no cookies (maybe a custom app that calls URLs), you would add an auth-token to the URL so that the user only logs in once per session. In this case you would create a data store which contains session data and associate both sessionId from browser and auth token to the same data. This is how I have done mobile/web/api session data management in the past.
What problem are you trying to solve?
I have a system that is deployed with the link http://192.168.2.6:8484/DTR and upon logging in, it stores the user's info via session.setAttribute("user", user); However, when another user logs in, it overwrites the info of the first user as it again calls session.setAttribute("user", user);. So how can I really save the user's info so that more than two people can access the system at the same time?
This is what is currently happening:
I have two websites that are open.
I login in the first website (username: user1). Shows Hello, user1
I login in the second website (username: user2). Shows Hello, user2
I refresh the first website. It will now show Hello, user2
So how can I enable multiple users to access the website?
As discussed in the comments, the reason is both the users are logged in from the same browser and same system. So the JSessionId is same and hence the attributes are overriden.
Solution:Try with a different browser
You first get user attribute and set it if it's not there and session is new
user = session.getAttribute("user");
if (user == null&& session.isNew())
session.setAttribute("user", user);
Also please check if you are getting different session for different users session.getId() ... if not it might be the problem JSESSIONID cookie. The servletcontainer set a Cookie in the Set-Cookie header of the HTTP response with JSESSIONID as cookie name and the unique session ID as cookie value.
Just wondering if my following authentication method is correct or not. Is there any pitfall or anything missing? Suggestions and discussions are very welcome.
1> User provide user name and password, and send to the server by RPC. Comparing with the hashed value stored in DB.
2> Assuming the user name and password are accurate, an Auth Token is saved in session. The auth token will be checked when accessing the servlets.
3> The user id (integer) is returned to the client by RPC onSuccess. The user id is saved in a static variable on the client side.
4> Whenever the user specific information is needed, the rpc call with the user id (the static variable) will be sent to the server for database query.
Thanks
You'd better return the token to client side, and verify token instead of user id.
If user id is used, a user A is logged in, then another user can send request to server pretended to be user A. Your authentication method failed to protect data.
You don't need to send a user id to the client. The server has already all information he need's to recognize the user.
This code snippet creates a session cookie, with session.getId() you get the content of it, which you should save to recognize the user:
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession(true);
Then when the user calls your Server, you just read back the session id.
HttpServletRequest request = this.getThreadLocalRequest();
HttpSession session = request.getSession(false);
With session.invalidate() you can destroy the session, it's also possible to store objects in the session.
The this.getThreadLocalRequest() only works in *Impl .
you quoted
3> The user id (integer) is returned to the client by RPC onSuccess. The user id is saved in a static variable on the client side.
If a user refreshes his page, the value that is stored on the client side static field will be reset, right? in that case will the session ends? and user will be prompted for login again?
When a user has an associated HttpSession object and then want to "log out" of the application you would invalidate that HttpSession which in turn would remove it from the map that the ServletContext keep of all sessions. But this only removes it on the server side, what happens on the client side? Does the user still keep keep the cookie with the session ID which now no longer has a corresponding session object on the server and keeps sending this to the webserver? And what happens when the user wants to login again after logging out?
I imagine the sessionId cookie will still be kept, but since this sessionId will not match any session object in the server's memory, it will be discarded by the server next time user tries to login again. On the server side it will be quite transparent, request.getSession() will return a new session object automatically.
I would like to add to the answer of maksimov.
Although the cookie is still present on the client side, it is possible for the server to delete the cookie also on the client side. Spring Security does that when a user logs out. Here's the code:
Cookie cookie = new Cookie(cookieName, null);
String cookiePath = //cookie's path
cookie.setPath(cookiePath);
cookie.setMaxAge(0);
response.addCookie(cookie);
The important instruction is cookie.setMaxAge(0). Setting the max age to 0 means the cookie has to be deleted. Thus, the server may ask the client to delete the cookie by sending it the same cookie with a max age of 0.
We have the following situation:
JSESSIONID is being sent by both cookies and URL, but because of a Adobe Flash BUG, they are different (actually, the cookie JSESSIONID is wrong).
What we would like to do is to use the URL JSESSIONID instead of the one sent in the cookies. In other words, when I execute request.getSession(), it should return the HttpSession associated to the ID in the URL and not in the cookie.
We looked into Tomcat7 source code and, in fact, Tomcat first parses the URL, searching for an identifier. Then it overrides it with cookies SESSIONID if they are present. Here is the code snipped in CoyoteAdapter.java (tomcat 7.0.26):
String sessionID = null;
if (request.getServletContext().getEffectiveSessionTrackingModes()
.contains(SessionTrackingMode.URL)) {
// Get the session ID if there was one
sessionID = request.getPathParameter(
SessionConfig.getSessionUriParamName(
request.getContext()));
if (sessionID != null) {
request.setRequestedSessionId(sessionID);
request.setRequestedSessionURL(true);
}
}
// Look for session ID in cookies and SSL session
parseSessionCookiesId(req, request);
parseSessionSslId(request);
We could disable cookies JSESSIONID at all, but we can't because we use it for all URLs in the website. We'd like to disable cookies for JUST THIS SPECIFIC URL.
Is it possible? Is there any other idea or workaround to solve this problem?
You could implement a custom servlet filter that would replace request, response and session objects with your own wrappers. The wrappers then can behave differently based on the URL, e.g. delegate or not to the original session instance. Though you won't be able to access session data for some other id, without changing Tomcat code.