Can session scope beans be used with Spring Session and GemFire? - spring-session

Can "session" scope beans be used with Spring Session and Pivotal GemFire?
When using Spring Session for "session" scope beans, Spring creates an extra HttpSession for this bean. Is this an existing issue?
What is the solution for this?

Regarding...
Can session scoped beans be used with Spring Session and GemFire?
Yes!
In fact, it does not matter which underlying "provider" is used with Spring Session either. For example, either Spring Session with GemFire/Geode (docs) or Spring Session with Redis (docs), etc, can be used and it will work just the same (in the same way).
As for...
If using Spring Session for session scoped beans Spring creates extra HttpSession for this bean, is this an existing issue?
Well, this is not exactly true.
You have to understand the underlying technologies in play here and how they all work together, including Spring Session, the Spring Framework, the Servlet Framework, your Web container (e.g. Tomcat), which is bound by the contract specified in the Java EE Servlet spec, and any other technologies you may have applied (e.g. Spring Security's Web support).
If we dive deep into Spring's architecture/infrastructure, you will begin to understand how it works, why it works and why your particular statement ("Spring creates an extra HttpSession for this bean") is not correct.
First, Spring Session registers an all important Servlet Filter, the o.s.session.web.http.SessionRepositoryFilter.
There are many different ways to do this, and the Javadoc for javax.servlet.Filter essentially hints that this is done via the Web Application "deployment descriptor".
Of course, given our menagerie of configuration options today, a Web Application deployment descriptor is pretty loosely defined, but we commonly know this to mean web.xml. However, that is not the only way in which we can configure, essentially, the Web Application's ServletContext.
Spring supports both web.xml based deployment descriptors as well as JavaConfig using the Servlet (3.0+) API.
In web.xml you would register (for example) the Spring Frameworks' o.s.web.filter.DelegatingFilterProxy, that delegates to an actual javax.servlet.Filter implementation (when Spring Session is in play, that would be the o.s.session.web.http.SessionRepositoryFilter, of course) which is also declared/defined as a "bean" (first this, then this) in the Spring container. This is necessary in order to auto-wire (inject) the appropriate Spring Session o.s.session.SessionRepository implementation (also a Spring managed bean defined in the container, e.g. for Redis) that knows how to delegate (HTTP) Session state management to the underlying "provider".
In the JavaConfig approach, the registration is performed via the core Spring Framework's o.s.web.WebApplicationInitializer concept. Read the Javadoc for more details.
Well, Spring Session provides such a WebApplicationInitializer to initialize (HTTP) Session management, the o.s.session.web.context.AbstractHttpSessionApplicationInitializer. Typically, when using Spring's Java-based Container Configuration and/or Annotation configuration approach, a developer would create a class that extends this Spring Session provided class and register the necessary configuration (e.g. connection criteria) for the underlying Session management provider; for example (see also this). The Config class is annotated with #EnableRedisHttpSession which imports the Spring #Configuration class that declares/defines the appropriate Spring Session SessionRepository implementation for the "provider" (e.g. again Redis), which is needed by the Servlet Filter (again SessionRepositoryFilter).
If you look at what the Spring Session AbstractHttpSessionApplicationInitializer does, you will see that it registers the Spring Session, SessionRepositoryFilter, indirectly via Spring Framework's DelegatingFilterProxy... from insert, then here, then here and finally, here.
As you can see, the Spring Session SessionRepositoryFilter is positioned first in the chain of Servlet Filters. The !insertBeforeOtherFilters is negated since the parameter in javax.servlet.FilterRegistration.Dynamic.addMappingForUrlPatterns(dispatcherTypes, isMatchAfter, urlPatterns...) is "isMatchAfter".
This is essential, since the Spring Session's o.s.session.web.http.SessionRepositoryFilter replaces both of the javax.servlet.http.HttpServletRequest and javax.servlet.http.HttpServletResponse. Specifically, by replacing the javax.servlet.http.HttpServletRequest, Spring Session can provide an implementation of javax.servlet.http.HttpSession (when HttpServletRequest.getSession(..) is called) that is backed by Spring Session and the provider of the developer's choice (e.g. Redis, GemFire), the whole purpose of Spring Session in the first place.
So, the Servlet Filters see the HTTP request/response before any framework code (e.g. Spring Framework's session scoped bean infrastructure), and especially before any of the Web Application's Controllers or Servlets, get to see the HTTP request/response.
So, when the core Spring Framework's session scoped bean infrastructure sees the (HTTP) Servlet request/response, it sees what Spring Session handed it, which is just an implementation the regular javax.servlet interfaces (e.g. HttpSession) backed by Spring Session.
Looking at the core Spring Framework's o.s.web.context.request.SessionScope "custom" implementation (which handles bean references/bean lifecycles for session scoped beans declared/defined in the Spring container), which extends o.s.web.context.request.AbstractRequestAttributesScope, you see that it just delegates to the o.s.web.context.request.SessionRequestAttributes class. This class is created primarily by Spring's DispatcherServlet, and defines all of its operations (e.g. setAttribute(name, value, scope)) in terms of the "provided" scope defined by the bean (definition) in question. See the source for more details. So the bean gets added to the appropriate HTTP session.
Sure, Spring "will" create a new javax.servlet.http.HttpSession on the first HTTP request, but not without Spring Session's infrastructure knowing about it, since what Spring is using in this case is an implementation of javax.servlet.http.HttpSession backed by Spring Session's "Session".
Also, getSession(true) is also just an indication that the HttpSession is "allowed" to be created if it does not already exist! A Servlet container simply does not keep creating new HTTP sessions for every HTTP request, so long as the session ID can be determined from the HTTP request (which is done via either URL injection... jsessionid or with a cookie, typically). See the javax.servlet.HttpServletRequest.getSession(boolean) for more details.
Anyway, the only other caveat to this entire story is, you need to make sure, especially for GemFire, that...
The Spring "session" scoped beans defined in the container are serializable, either using Java Serialization, or 1 of GemFire's serialization strategies. This includes whatever the bean references (other beans, object types, etc) unless those "references" are declared transient. NOTE: I am not entirely certain GemFire Reflection-based PDX serialization approach is entirely "aware" of "transient" fields. Be conscious of this.
You must make certain that the classes serialized in the session are on the GemFire Servers classpath.
I am working on a configuration option for Spring Session Data Geode/GemFire at the moment to support PDX, but that is not available yet.
Anyway, I hope this helps clear up the muddy waters a bit. I know it is a lot to digest, but it all should work as the user expects.
I will also add that I have not tested this either. However, after reviewing the code, I am pretty certain this should work.
I have made it a task to add tests and samples to cover this situation in the near future.
Cheers!
-John

Related

Why do you use DelegatingFilterProxy in springSecurity and what are the benefits of this design?

What I don't understand is why this security framework USES proxy classes to invoke filters. What are the benefits of this design?
I think the documentation of DelegatingFilterProxy gives you quite pretty explanation:
[...] All
calls to the filter proxy will then be delegated to that bean in the
Spring context, which is required to implement the standard Servlet
Filter interface.
This approach is particularly useful for Filter implementation with
complex setup needs, allowing to apply the full Spring bean definition
machinery to Filter instances. Alternatively, consider standard Filter
setup in combination with looking up service beans from the Spring
root application context.
NOTE: The lifecycle methods defined by the Servlet Filter interface
will by default not be delegated to the target bean, relying on the
Spring application context to manage the lifecycle of that bean.
Specifying the "targetFilterLifecycle" filter init-param as "true"
will enforce invocation of the Filter.init and Filter.destroy
lifecycle methods on the target bean, letting the servlet container
manage the filter lifecycle. [...]

What is the default scope on actions in struts2? [duplicate]

My question is not only if action classes can be scoped to singleton, but I also want to know which are the best practices. Both in context of Struts2 and Spring. Best scope of VIEW (say request or session), for controller and model.
Struts2 Actions are managed by the Struts Container. They are ThreadLocal, hence every request has its own thread-safe copy of the Action.
If you use Spring to handle them through the Struts2-Spring-plugin, there are multiple levels of usage:
you can let the Struts container instantiate them, and handle them through Spring for the Dependency Injection, or
you can let Spring take over control and be fully responsible for the whole lifecycle of every Action. In this second case:
if you declare an action as a bean in a Spring XML configuration file, the action will get the default Spring scope, that is Singleton (scope="singleton"). THIS IS DANGEROUS, USELESS, and 99.99% of the times NOT WHAT YOU WANT, because you will lose a fundamental part of the framework capability, actions will be turned into kind-of servlets, thread-UNsafe, and many problems will arise;
to prevent that, you can put the scope="prototype" in the bean declaration, that will let Spring instantiate the action without affecting its nature.
If you are inside a container Java EE 6+ compliant (for example, Jboss 7, Wildfly 8, TomEE 1.7, Glassfish 3+, ecc...), the Contexts and the Dependency Injections are handled through CDI. If you want, you can use the Struts2-CDI-plugin to allow CDI to handle your actions and inject dependencies through the #Inject annotation (instead of the #Autowired one)
I've used Spring a lot in the past, then after discovering CDI and the CDI plugin, I've switched and never looked back, so I vote for the n.3

Can Spring Session be setup in an application not running a spring application?

We have a CMS running in one tomcat container, that is not a spring application. We also have multiple applications running on separate tc server instances that contain our custom code (account management, cart, etc.). These are all spring 4.0.x applications and are secured with Spring Security.
I would like to enable Spring Session between all of these environments. Do you foresee any issues using Spring Session in an environment such as this?
Spring Session should work on projects that are not otherwise Spring. If you take a look at the HttpSession Sample listed in the Samples section of the reference and you will see it works just fine with a standard servlet too.
In fact, depending on how you choose to integrate, Spring Session requires no additional dependencies on Spring at all. For example, the Hazelcast sample demonstrates how you don't need any Spring dependencies (other than Spring Session itself).
The possible problems I'd foresee:
If your CMS uses session very heavily, then the IO of retrieving your Session on every request can slow down things significantly
The SESSION cookie is how the session is stored in the browser and then passed back to the application. Spring Session by default writes this in a cookie with the path of the context root. This means that the SESSION cookie will not be visible to all of the applications. You can customize this with your own implementation. You can follow issue 87 for progress on making this available by default.

Authorization using Spring-Security (or) Spring only

I have question related to authorization and spring security. To implement authorization checks in one of my services (under a Service Oriented Architecture environment), I was trying to see if I can use Spring-Security. While going through the Spring Security documentation, I read here that spring security uses spring's AOP internally.
Ref: You can elect to perform method authorization using AspectJ or Spring AOP, or you can elect to perform web request authorization using filters. You can use zero, one, two or three of these approaches together. The mainstream usage pattern is to perform some web request authorization, coupled with some Spring AOP method invocation authorization on the services layer.
We are already using Spring AOP in our service implementations. In my case, the requests that will be coming to my RESTful service will carry a custom built token object that should be processed to perform authorization checks.
Based on this, I would like to understand if I can simply use Spring and create an Aspect to catch an inbound request, extract and process the associated (custom built) token and continue/reject the request based on the result ? Do I need spring-security, given that the communication channel is already secured using HTTPS ?
Thanks,
SGSI
For a similar situation we did the following a long time back:
Used an HTTP filter to extract a token from HTTP headers for each request.
Stored the extracted header to thread context.
Added an aspect around service method calls to check the thread context for the token.
This strategy worked well for us. For last many years I have been using Spring Security since it has a more tested and comprehensive implementation for such problems.
If you wish to write your own token-passing implementation, you can check the source code for the Spring Security class SecurityContextHolder that provides multiple ways of passing security information on the execution thread.

How to store spring security session information in redis?

I am using Spring security for Authentication and Authorization in my application. I am using Neo4j database as backend and implemented userDetailsService for authentication.
However, whenever my application restarts, user is forced to login once again.
To overcome this, i am thinking to store session information in redis database and load the data to Spring security Context whenever application gets started.
Kindly pass on if there are any articles and pointers to implement the same.
I am thinking of following implementation for it,
1) For every successful authentication, store user details and session details in redis.
This must be implemented in loadUserByUsername() method of UserDetailsService implementation
2) Remove the data from redis, whenver user logs out, Where can i do this information? Is there any spring security function where i can call this
3) Load all the data from redis to spring security whenever application restarts, again where do i need to write this logic?
Please let me know if i have missed any information.
All you need to do is to implement a
SecurityContextRepository that handles security context storage to reds
Eventually a custom filter that retrieves/ stores session information (GenericFilterBean)
I think it is possible to just give the standard filter a different repository, but I am not sure, I needed my own implementation anyway...
Store session in a redis is out-of the box functionality now
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession.html
You need to configure remember-me feature of Spring Security.
Remember-me or persistent-login authentication refers to web sites being able to remember the identity of a principal between sessions. This is typically accomplished by sending a cookie to the browser, with the cookie being detected during future sessions and causing automated login to take place. Spring Security provides the necessary hooks for these operations to take place, and has two concrete remember-me implementations. One uses hashing to preserve the security of cookie-based tokens and the other uses a database or other persistent storage mechanism to store the generated tokens.
More information available in Spring Security documentation:
http://static.springsource.org/spring-security/site/docs/3.1.x/reference/remember-me.html
You can use out of box implementations or inject your own (aforementioned redis).
As Luke Taylor said, Tomcat's default action is serialize/deserialize sessions on container restart.
Here
pathname attribute of standard manager is the name of the serialization file. If you dont specify a path name attirbute the default is SESSIONS.SER
If you dont want to have sesssions back when restarted, you need to specify it as empty string value..

Resources