I'm using Spring for my web app. I have used several SimpleFormControllers. I've created a session in the first SimpleFormController for the login page using:
HttpSession session = request.getSession(true);
How can I protect other SimpleFormControllers using Sessions, i.e. so that other controllers won't load if the user is not loged in.
Thank you
You probably want to use Spring Security.
It's flexible and allows restrictions based on roles.
Without it, you will need to manually check in every controller whether the user logged in or not. Or you'll have to "reinvent" a security framework by adding filter to the webapp.
If you only want to protect the operation of getting the session, you need to write a filter that wraps the original request and overrides the getSession methods. There you can check for login data using the original request's getSession().
BTW, getSession() is equivalent to getSession(true)
To protect the Controller from access outside of the intended Session, you may want to compare the Scoping rules you need with this clearly written Guide.
How to get Session Object In Spring MVC
The author gives an example of creating a Controller annotated with #Scope("session")
Related
I have a REST service implemented using Spring MVC (RestControllers) with token based security (using Spring Security). How can i filter resources depending on user identity? Let's say user has some reports. How can I let authorized user by performing a call to /reports to see only his reports?
Obviously i can make userId to be a request parameter or path variable, but something tells me that this is a bad practice.
I assume i can achieve that using Spring Security features, but how exactly could i do that and, more important, where is the most appropriate place to apply such filtering? Should controllers perform calls to services passing user identity or should it be somehow retrieved at repositories level (I use Spring Data JPA)?
Thanks in advance
You have Authentication object whenever a user is successfully logged in.
It contains Object principal Object credentials and Set authorities.
All you need to do is override UserDetailsService to add new parameters for your authenticated user. Add your userId in authentication as shown in blog
Now when you do
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
this will return you the User object of the spring security.
You can get the user id from here and use this in controller to do necessary actions.
In an server application I use bare websockets without the spring messaging layer and sockjs/stomp. I need my own messaging layer on top, but I want to use for example spring session to leverage the servlet HttpSession replacement to keep the http session alive which is beneath the websocket session, to prevent timeouts. The websocket is opened from a static HTML-page using JavaScript.
In the spring-framework documentation there is all the necessary information to setup bare websocket support with e.g. a basic BinaryWebSocketHandler or TextWebSocketHandler as well as how to
provide your own HandshakeInterceptor.
I've added spring session 1.1.0.RC1 with hazelcast for storing sessions and replacing the servlet container HttpSession implementation with the Session/ExpiringSession proivided by spring session. I just followed the given instructions to do this.
So far everything is fine, but as I'm serving a static HTML page from which I open the websocket using JavaScript without using spring security or any other mechanism to trigger a processing by the servlet container, no http session is intialized so far.
So the question is: How do I intitialze the custom HttpSession which is then stored in a the SessionRepository provided by spring session?
Note: I will provide an answer myself as I think I solved the issue for my case and it may be helpful for others facing a similar problem.
As can be seen from the spring-framework documentation, it is possible to add a custom HandshakeInterceptor. Spring session offers the
// example for reference:
org.springframework.session.web.socket.server.SessionRepositoryMessageInterceptor
which targets the spring messaging layer. It shows how to reset the timer of the HttpSession prior to sending a message within the method preSend(...) as well as how to optain the HttpSession from the request in the method beforeHandshake(...).
I implemented my own HandshakeInterceptor based on this with an almost identical beforeHandshake(...) method, but with one minor difference and of course leaving out the ChannelInterceptorAdapter stuff. The reset of the HttpSession time has to be done somewhere else, but that is out-of-scope.
Because in my case no HttpSession has been created so far, I changed the line obtaining the session from the request to look like this:
HttpSession session = servletRequest.getServletRequest().getSession(true);
Changing the boolean parameter from false to true in the method getSession(...). Now this call will trigger the creation of a new HttpSession (provided by spring session) if none is available so far.
This solution seems to do what is required in my case. Please correct me if I'm missing something or using anything the wrong way.
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.
I'm using spring MVC, and I have a custom authentication/security system that I had to build.
NOTE: I know of spring security, but my requirements were to do this in a custom way so please not looking for suggestions about using spring's security modules.
When the user logs into the system, it creates a session cookie. When the user visits a page, a interceptor looks for the existance of that cookie, and looks up the session guid in mysql and if it is present that it loads some data and stores it in the request's attributes.
Now for pages where the user has to be logged in, how can I restrict access at the controller level?
I could do this in an interceptor:
if url.contains("projects/") ...
If I want to restrict access to only logged in users in the ProjectController, but this isn't really something I want to do.
But I am looking for maybe a annotation I could add at the controller level, or maybe somehow create a BaseController that all controllers that require a loggedin user will inherit from.
What are my options for something like this?
In ASP.NET, I created a baseController, and the controller has an event cycle, and in the before-action fired event I checked to see if the user was logged in.
So looking for suggestions for spring mvc?
Update
For example, in ASP.NET you have 2 methods, 1 that fires just before the controller's action method and one that fires after:
Controller.OnActionExecuting
Controller.OnActionExecuted
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onactionexecuting.aspx
So in the OnActionExecuting, I can actually see exactly which controller I am in, and which action is about to get called in a programatic way, not by looking at the request URL and then doing string compares to see if it is a particular controller etc.
So in this event, I can simply check for things in cookies or in my request attributes etc.
This is a much more stable way to do it, does spring have anything similiar?
If you need this at the controller level, you could:
1) declare a java.security.Principal parameter in the controller method signature, which Spring will fill in with a Principal object, or
2) implement a PermissionEvaluator, which can be called on a controller method using the #PreAuthorize annotation, and which would have access to a Authentication object.
Similar to what you did in ASP.NET, you can take advantage of OncePerRequestFilter and chain it to the chain of filters you have in web.xml or Spring application context. The good point about this filter is that it's independent of the MVC approach that you take and no need for a "base controller".
On the other hand, if you're also using Spring security module, you can use a custom filter configuration and place it in the correct place that it should be.
If the check fails, then you'd probably want to raise exceptions or redirect user to the correct navigation.
Based on the last comment, you can also use mapped interceptors:
<mvc:interceptors>
<mvc:interceptor>
<mapping path="/myFirstPath/*"/>
<mapping path="/mySecondPath/*"/>
<bean class="org.example.SomeInteceptor" />
</mvc:interceptor>
<mvc:interceptor>another one</mvc:interceptor>
</mvc:interceptors>
I have my user session stored as an <aop:scoped-proxy/> proxy. how would i go about accessing it on the jsp?
i am assuming that the bean is stored somewhere in the session, correct me if i am wrong.
i found an answer:
http://digitaljoel.nerd-herders.com/2010/11/01/accessing-spring-session-beans-in-jsp/
in short:
${sessionScope['scopedTarget.userSession'].firstName}
works like a charm
Check out this thread. The issue is that session scoped beans (or beans in general) must be injected into the classes that need them and there isn't an easy way to do that with JSP pages. In addition to the solution presented in the thread I linked, you could also inject the user session into your controllers and then add the object to your model. Alternatively, if you wanted to switch to a framework like Spring Security for your user session management, you could make use of their tag library to access the user session information from a JSP.