Spring session for session sharing(clustering) between servers - spring

I'm trying to let two machines with the same base domain (subdomains differ) to share session.
spring-session-jdbc seems to be a solution I could use to achieve the goal.
When a user logs into server-a, session info is stored in SPRING_SESSION db.
What worries me is the fact that custom org.springframework.security.core.userdetails.UserDetails class is stored in that db as well.
When server-b tries to read session data from the db, it has to use the same custom subclass of the org.springframework.security.core.userdetails.UserDetails.
So I'm copying codes that relates to the UserDetails class from server-a to server-b.
I'm feeling a little awkward doing this, because server-a and server-b might want different UserDetails in general.
Is this really intended way of using spring-session-jdbc ?
Another question is, is it mandatory to use spring-security for both server-a and server-b?

Spring Session is meant to easily enable session clustering, i.e. have the multiple instances of the same app share the external session store therefore making it easier to scale your app.
For the problem you are trying to solve it might be a good idea to use an appropriate higher level protocol such as OAuth 2.0 and OpenID Connect and implement single sign-on without coupling you applications through the session store.
While the idea of sharing session store between different apps might seem convenient initially, such arrangement is usually very problematic, as you noted yourself with the UserDetails example.

In line with Vedran Pavic's answer it sounds like you should be using sso. That said there are instances where different code bases may want to share the same session such as in micro-service clusters. In this case you should simply put your UserDetails into a base jar/module that the other jar/module's are dependent upon. You can use a build automation tool to make this packaging easier to accomplish.
To answer your final question, if these two applications are regularly communicating with each other then I'd recommend either using spring security everywhere or nowhere.

Default mechanism to persist and load session is through the SecurityContextRepository (Spring Security) or SessionRepository (Spring Session).
If you use Redis for session sharing the repository implementation could be RedisSecurityContextRepository (spring-security-redis) or RedisIndexedSessionRepository (Spring Session).
The latter one for sure serialize UserDetails so you cannot share the session unless you use same Frameworks & user classes versions.
I would use custom SessionRepository and store shared user info in portable Json or XML, or whatever you like, not the Java object serialized ))

Related

Spring and Vaadin contexts communication

Implementing of UserDetailsService is common way, which in Spring login process is used to acquire some extra data (except username and password) entered by user. Problem is, how this extra data can be passed to Vaadin context (for example VaadinRequest), that need to work with it. In UserDetailsService Vaadin context is not straight accessible - or maybe somebedody knows how to do this (but I don't) - and this is my problem. Level of access is also important - Spring context and Vaadin context should by distinguished and should communicate to each other on the level of logged-in user - they should not be shared by multiple users. So can somebode help me with this? ... of course another alternative approach of communication between this contexts wil be welcome. Thank you for advice.

Uniqueness of Session ID in a Distributed environment?

We are using Spring Session (backed up with pivotal Gemfire) for our Spring Boot applications running in an Distributed environment.
In such a distributed environment,
does Spring Session ensure that a unique session id is used for new
sessions being created across different JVMs ?
Just reviewing old SO posts for Spring Session Pivotal GemFire support, so my apologies your question never got answered in a timely manner.
In a nutshell, Spring Session uses the UUID class to generate "unique" Session IDs. For instance, see here, or more generally, here.
NOTE: Spring Session Data Redis support uses/wraps the MapSession class to store Session state in Redis, by default.
There are appears to be a lot of discussion about the effectiveness, or rather uniqueness, of UUID across JVMs in a cluster. This one in particular, though dated, caught my attention as it originated from the Oracle Java community forums.
However, keep in mind that it is your application(s) use of Spring Session that ultimately determines whether Session IDs are unique; i.e. it is not dependent on the number of nodes in a GemFire cluster since individual GemFire nodes are not generating the Session ID (applications using Spring Session are).
Therefore, if only 1 application (probably not likely in the Microservices state of the world) is ever present with Spring Session in use, then the UUIDs are probabilistically guaranteed to be unique. Even then, based on references available, it seems highly unlikely that 2 or more "application" nodes employing Spring Session will ever generate IDs that collide (though, (almost?) anything is possible ;-).
Though, I suppose if it is of paramount concern/importance, following with the beautiful tradition of Spring, it would be a simple matter to extend the GemFireOperationsSessionRepository and override the createSession() method, calling the appropriate GemFireSession constructor to pass the desired Session ID in.
However, in all cases (GemFire, Redis, etc), the Session ID uniqueness problem is agnostic of underlying, backing data store.
Hope this helps...
Cheers!

Is there a way to bypass all security checks in Spring Security?

I'm coming from the PHP world. The framework I used most is Symfony which is heavily based on ideas from Spring. One if its bundles called JMSSecurityExtraBundle supports a role ROLE_IDDQD that you can activate via configuration. Authenticating with that role would effectively bypass all the security checks — be those Web security constraints or constraints directly on methods of classes in the domain layer.
Since security related tests needed a user with a particular role to be authenticated, I would authenticate a user programmatically creating an authentication object and passing it to the security context. That way I could test security constraints directly on the domain code without involing any UI.
Since a lot of domain methods would be secured, it would prevent me from setting up fixtures for some of the tests because the currently authenticated user wouldn't have enough permissions to do that. This is where I started using ROLE_IDDQD — I created a method that would take a function that could do anything in the domain layer bypassing any security constraints:
$user = $this->iddqd(function () {
return $this->userManager->save($this->aUser());
});
That method would remember the current authentication, reauthenticate with ROLE_IDDQD, execute the function passed in and then restore the remembered authentication.
I'm migrating the app to Spring and looking for a way to do the same with Spring. I couldn't find any mention of ROLE_IDDQD, so I guess that part wasn't based on Spring Security. Are there any other means to replicate this functionality?
Spring security has a concept of Anonymous user with automatically assigned role "ROLE_ANONYMOUS". You can look for more information here
I solved the problem a long time ago. Here's how I did it.
In my architectures, I usually have a repository layer that abstracts away database access and a manager layer above the repository layer that enforces domain logic.
The problem was in my approach to testing. I tried to use managers to set up test data. I now do it directly using repositories and there's no need for hacks like IDDQD roles and such.
So, basically, I use repositories to populate databases with test data, and then I hit managers to test domain logic in them.

Custom session state management

Can someone point me to example implementation for custom session state management ?
I am looking for following approach "keep all the session state in database and keep only the keys in HttpSession object. "
Can it be done using Spring ?
TIA
-Vin
Using a plain old java proxy for this (or cglib proxies) should be possible, you still need to handle saving/loading to/from your db. There's also the issue to see if a proxied object has been modified this would have to been handled additionally. Spring does not anything to this AFAIK.
Not sure what you're trying to achieve really, but perhaps also memcached-session-manager is interesting for you (shameless plug :-)).

Scope confusion regarding session beans, proxies, and singletons in a Spring 3 managed JSF app

This seems like it's basic Spring 101 stuff, but I can't seem to find the correct way to do this. The situation is as follows; in my web app there is a single entry point which is a controller that handles users coming from an outside system. The transfer is just a POST request with a bunch of associated information pertaining to that user. Apon entry, I need to create a new User bean and load it with that users information. Additionally, when the user hits a view which triggers some service, I need for that service to be able to access the appropriate User bean instance.
The first way to do this that came to mind was to have a UserManager service which would create a new instance of User, fill it w/ data, and then register it in the Spring container with the username as the bean name. Then when a service is invoked, the service would do something like Factory.getBean(username) to find the appropriate User instance. The problem I see here is that I'm losing the link between the user & which User bean belongs to them. Additionally, I'd like to avoid having the user carry the bean around in the session if at all possible. Is this where I am supposed to be using Spring AOP & proxies?
What is the typical Spring pattern for solving this type of situation?
So it is now many weeks later (since asking this question), and consequently my knowledge level has been expanding exponentially, so I figured I might as well answer my question for anyone who might find it helpful (not to mention the question wasn't very clear to begin with).
The basic answer is: use proxies. Since a singleton is only instantiate 1 time, you cant inject another class which has a shorter lifespan, eg. session scope. For those requiring more information, checkout stateful vs stateless beans. More or less what I ended up doing is this... the services contain STATELESS code for manipulating data (think verbs; RegisterUserSvc, AddPartSvc, etc). The data which these services manipulate is stateful. For instance, each user has a own copy of their own data object, lets say TodoListBean, which is in a different state for each user.
So how does a service, AddTodoItemService for instance, manipulate this data? This is where the proxy comes into play. When instantiated, the AddTodoItemService gets injected with a proxy for the TodoListBean, instead of the actual object. That way when the service needs to access the TodoListBean the container will serve up the a TodoListBean out of the current users session, and therefore the service will be operating on the correct bean (based on which user invoked the service), instead of doing something silly like having numerous copies of the service included in each users session scope.

Resources