Spring #ResponseBody can not use session - java

I have angular2 app and use Tomcat with spring for getting data. I don't want any page reloads or redirects, all I need is data, so all responses from server have #ResponseBody annotations.
My problem is, that because of this annotation I can not get users session variable. When I log in I create session, store user data in it but can not get it with next call.
#JsonIgnoreProperties(ignoreUnknown = true)
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String login(HttpServletRequest REQ, #RequestBody String BODY) throws Exception
{
...check if all ok...
REQ.getSession().setAttribute("user", user);
... return user data...
}
Is there any other way I can send my data back to client, together with the data needed, to be able to use session.
Edit:
Problem is not on server side but client. Angular is not sending cookie JSESSIONID at cross domain requests by default.

First check your request/response (for example in Chrome dev tools). Tomcat creates new cookie named JSESSIONID to bind client with server session object, so look for this one in your login method response header. Then make sure you are sending this cookie back to your server in next request. Session creation has nothing to do with Spring or #ResponseBody, its lifetime is managed by container (Tomcat).
Also, if you are making cross domain requests, check this answer.

Anything you put on the session context isn't available to clients, it's only available to the server. see this stack overflow post for a good explanation on how servlets work, and specifically the part on how session state works.
As you can see, it works by adding a session-cookie to the response which contains a session-Id. The server stores the session state under that id in memory, and when a future request comes with that session-id, it makes the session state available again to the future request.
If your next requests do not have access to the session state, it's quite possible that the session-cookie isn't propagated properly. I suggest you check that first. It should be in the response where you log in, and should be posted in further requests to the server.

Related

Programatically expired spring session causes the rest-api user to face unexpected response

There is an adminUser A who can make the session of another rest-api user B expired.
Collection<SessionInformation> usersSessions = sessionRegistry.getAllSessions(user, true);
usersSessions.forEach((temp) -> {
temp.expireNow();
});
Now, when the user B tries to make any rest request for the first time, it gets following 200 response without any content-type
This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).
I wanted to send the user a proper response something like INVALID_SESSION with a proper HttpStatus, so I tried to intercept the servlet with a custom org.springframework.web.servlet.HandlerInterceptor (which works in other scenarios), and I observed that even the preHandle method was not being called.
It seems that the response is being sent during the session verification process. I have no idea how does this actually work. Is there a way to get custom response? Can javax.servlet.http.HttpSessionListener be useful?

How does Spring detect a session?

Here is how i think session detection works in a standard way.
The user authenticates
The backend generates a sessioncookie
The backend sends the cookie in response to the client
The user sends back the cookie with every new request
And Spring detects the right session by identifying the cookie.
Here is my problem:
I am currently working on a javafx client and use springs own kind of RMI via AuthenticationSimpleHttpInvokerRequestExecutor to make my authentification. It works fine, but i save some data in session-scoped beans. I fill these beans in the first request and expect my data to still be there at the second request. But with every request i get a new (empty) session-scoped bean.
I guess spring does not recognize the session and opens a new one. Thats why i get new session-scoped beans with every request.
AuthenticationSimpleHttpInvokerRequestExecutor does not send any cookie but it sends username and password as http-basic-authentification with every request. So there is plenty of Information left to still find the Session and inject the correct session-scoped Beans. Why does not spring use username and password to identify a session?

Session management using spring security

I have created a basic spring security authentication using UserDetailsService and now I am able to validate user. However, I don't understand how to achieve below things:
Once a user is logged in, when next request comes how and where do I check if the request is coming from the same logged in user or other logged in user?
I know the concept of Spring interceptors where I can intercept all incoming request. But is there something in spring security that does this?
How can I start a session after logging in and store values in session for that user?
I browsed through existing answers but most of examples are for logging in.
I would appreciate if someone can give me examples.
EDIT:
I think I should use session scoped beans in order to maintain user's session contents rather than manipulating httpsession directly.
I think you really need to spend some time reading the Spring security documentation and over all JSP, servlet and MVC architecture. You have several misunderstandings,
After authentication, you don't need to start a session it was already there when the request came. Remember request.getSession()we get the session from the request and I am really NOT aware of any other way i.e. instantiating session object and assigning it to request/response. After successful authentication spring automatically sets a SPRING_SECURITY_CONTEXT attribute in session and this variable is later used to determine whether user is already authenticated or not (Spring does that for you, you don't need to use this attribute).
In spring security we set an authentication entry point which has information about login page url and FORM_LOGIN_FILTER which has information about login processing url, login success url and login failure url among few other things.Every request whose session doesn't have SPRING_SECURITY_CONTEXT and auth attribute gets redirected to login page url.
I could give the code directly but it would be great if you read at least few pages of Spring documentation here. Once you understand the concepts and are still not able to solve the problem. Edit your question with detailed problem and we will try to fix it.
At first you need to create an Authentication object using current HttpRequest as below:
public class SessionService{
public Authentication getSession(HttpServletRequest request) {
HttpSession session=request.getSession();
SecurityContext ctx= (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
Authentication auth=ctx.getAuthentication();
return auth;
}
}
Then, you can retrieve the session details from this Authentication object by passing the current HttpRequest as follows:
Authentication auth = sessionService.getSession(request);
The above auth object contains the details that you need.

How can I store state for an individual browser tab/window?

I'm developing a single page jQuery & Backbone.js web app. The backend is a JBoss 6 application server.
Until now we had the following structure:
There is only one servlet (front controller). Every request from the JavaScript client goes through here.
In the servlet - at the first request of a certain JS client - I make a look p to a stateful session bean. For the next requests of this client, I store the result of the look up in an HTTP session container. So every JS client has exactly one stateful session bean. This connection is kept by a session cookie.
Now I have an additional requirement:
When the user has two browser tabs (in one browser), they should have two isolated instances of the web app in every browser tab. Because of that I have a problem with session cookies because this session cookie is for all browser tabs.
I have to change the structure so that:
The servlet has to generate a new session ID for the first request of a certain JS client. This session ID is communicated to the client.
With every POST to the backend the JS client has to send this session ID.
My question is:
Until now I saved the result of the look up in an HTTP Session object and I hadn't to think about generating a session ID. But now I have to store this somewhere else, where?
Has anybody experience with this kind of setting and can help me?
Update:
Thank you BalusC for this very interesting approach.
When I understood you well, this means:
All individual JS clients of the tabs of one browser share one HTTP session object. And in this HTTP session object, every tab has its own entry point. That sounds really good. So I still can use the whole HTTP session infrastructure and don't have to reinvent the wheel.
Autogenerate an unique value on the initial GET request which you store and pass around on every subsequent postback as a hidden input value. Use this unique value as identifier of the session attribute representing the view-scoped data.
During the 1st request on a brand new session, do:
Map<String, ViewData> viewScope = new HashMap<String, ViewData>();
session.setAttribute("viewScope", viewScope);
(the ViewData represents the view-specific data you'd like to track across postbacks on the same view)
During every GET request, do:
String viewDataId = UUID.randomUUID().toString();
viewScope.put(viewDataId, new ViewData());
request.setAttribute("viewDataId", viewDataId);
During generating the HTML, do:
<input type="hidden" name="viewDataId" value="${viewDataId}" />
During every POST request, do:
ViewData viewData = viewScope.get(request.getParameter("viewDataId"));
// Get/set view-specific data in there.
Make sure that jQuery also passes this hidden input around (which shouldn't be a big problem if you already properly use $(form).serialize() or e.g. AjaxForm plugin to ajaxify the forms).
If you're familiar with Java EE's MVC framework JSF, then it may be useful to know that its #ViewScoped annotation works roughly the same as described above. See also a.o. How to choose the right bean scope?
You can use session tracking with URL rewriting. See here:
Session shared in between tabs

HttpConnection maintaining Session

I'm consuming some web services done in java using a Rest architecture, my client it's a mobile application that uses HttpConnection to retrieve the data. In order to control authentication and authorization I'm using cookies, managed by a #SessionScoped class, however I don't know how to make the session persist through requests. The problem basically is that I inject the Session manager in other services that are #RequestScoped, however since the session is not persisted I always retrieve differente instances for the #SessionScoped class, thus deleting all the cookies or records I had before. Looking at the request headers I noticed the cookie JSESSIONID, I think this is sent by tomcat in order to persist session, so tried already to send the same cookie in the next request, however I got no results.
The comments were right... to persist a session you just have to send the JSESSIONID cookie back to server in the next request, the problem in this case was that HttpConnection in JavaME only has the setRequestProperty method to include a header value, now if you set the same value two times it overwrites the last one. Since I was using a custom cookie and the JSessionID cookie, I setted them in the following way:
connection.setRequestProperty("Cookie","sessionId="+ApplicationPreferences.getIn‌​stance().getSessionCookieHeader());
connection.setRequestProperty("Cookie","JSESSIONID="+ApplicationPreferences‌​.getInstance().getJavaSessionCookieHeader());
When the correct way to do it is concatenate the cookie strings and then setting a Cookie header with them all:
String myCookies="sessionId="+ApplicationPreferences.getInstance().getSessionCookieHead‌​er()+";"+"JSESSIONID="+ApplicationPreferences.getInstance().getJavaSessionCookieHeade‌​r();

Categories