New session for each call to the Spring Boot server with JWT problem - spring

I'm working to limit the number of sessions per user in Spring Boot, so as to limit the number of devices it can connect.
this is my WebSecurityConfigurerAdapter:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).maximumSessions(10).maxSessionsPreventsLogin(true);
I tried to change SessionCreationPolicy in various states, or not declare it:
http.sessionManagement().maximumSessions(10).maxSessionsPreventsLogin(true);
every time I call the server, a new session is generated, up to exceeding the declared limit, so I am no longer authorized to make a call.
I noticed that the creation of the new session takes place in GenericFilterBean, exactly after running filterChain.doFilter (req, response)
I carry the file GenericFilterBean:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
{
...
**filterChain.doFilter(req, response);**
...
}
do you know the way to avoid that every call to the server generates a new session? My goal is one session for each device.
Thanks a lot for availability !!!

Related

How to not lose Request attributes when making async (asynchronous) from one Rest Service to another

Currently I'm facing the following issue:
Rest service (Implemented using Spring Boot)
Inside my rest service I need to make an asynchronous call to another rest service.
I'm using #Async into the public method that will perform the async call.
I'm using Feign Client to make that rest call.
I'm intercepting the request using a feign.RequestInterceptor
Now the problem:
In the current implementation of the RequestInterceptor we have
#Override
public void apply(RequestTemplate requestTemplate) {
/// Getting a NullPointer here as obviously we have changed the from one thread to another
/// when the async call was made
final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
//some other irrelevant logic for this example....
}
As we move from one thread to the spawned thread, the information is lost.
I'm assuming it has to do with the threadlocal and somehow I should pass the information to an inheritablethreadlocal.
What should be the approach to be able to pass the ServletRequestAttributes to the spawned thread, without losing the information? (basically I'm interested in be able to preserve headers that came in the original thread).

Count AsyncResponse calls in spring boot metrics

I have a JAX-RS service backend written in Spring boot 2 and using micrometer for metrics.
By default the metrics contain very nice http metrics as http_server_requests_seconds_count.
These work great for normal GET and PUT requests. One method in my service uses JAX-RS AsyncRequest though.
#GET
#Produces(APPLICATION_JSON)
#Path("next/{position}")
public void getNext(
#PathParam("position") Long position,
#Suspended final AsyncResponse response) throws InterruptedException {
...
// Somewhere in the code in another thread I invoke
response.resume(entity);
...
}
These calls do not seem to be counted at all. Is there a way to enable counting them?
If not should I simply feed the same counters manually from my code?

Spring SecurityContext in Async Controller Response

According to WebAsyncManager documentation,
An async scenario starts with request processing as usual in a thread (T1). Concurrent request handling can be initiated by calling startCallableProcessing or startDeferredResultProcessing, both of which produce a result in a separate thread (T2). The result is saved and the request dispatched to the container, to resume processing with the saved result in a third thread (T3). Within the dispatched thread (T3), the saved result can be accessed via getConcurrentResult() or its presence detected via hasConcurrentResult().
The Spring SecurityContext is available in T1 and T2, but not in T3. I need the SecurityContext in T3, while serializing the response (it's a peculiar requirement). I can fix this by setting
spring.security.filter.dispatcher-types=REQUEST,ERROR,ASYNC, but this causes my entire FilterChain to run twice, which I'm trying to avoid.
Is there a way to get the SecurityContext in T3 without running the FilterChain again?

Why filter chain is called twice for an asynchronous endpoint

I'm developing a Spring boot based app. I noticed that for asynchronous endpoints authentication filter is called twice, for regular endpoints it's called once. I couldn't find the reason, but I found an issue in the net https://jira.spring.io/browse/SPR-12608 , where it's said that filters for async endpoints are called twice, before and after async endpoint execution. It would explain double authentication call. I'd like to know is this expected behavior, why it's done like that and how to avoid double authentication.
UPD:
I found a way how to avoid filter being firing second time after async endpoint finished. The thing I need to do is to analyse what kind of dispatcher is assigned to the request, if it's async - proceed further on filter chain. I added the following method to the filter:
#Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getDispatcherType() == DispatcherType.ASYNC) {
filterChain.doFilter(request, response);
} else {
super.doFilter(request, response, filterChain);
}
}
I am seeing exactly the same behavior and I think it is related to the fact that asynchronous call is being split into 2 phases.
At first, regular container thread is kicked and an interim response is generated, but that response is not being returned to the client it is being held back until async dispatcher competes. Once async thread is done processing interim response is replaced with the real one from async thread and returned to the client.
Both threads go through the same filter chain. Therefore you see duplicate invocation.
If you want your filter to be invoked once you should extend from OncePerRequestFilter. It will check if your filter was already invoked during the course of the request (even though the request handling consists of 2 stages each of them handled by their own threads).
I had the same problem with a concrete implementation of the class AbstractAuthenticationProcessingFilter, I belive to solve it It's better create a custom implementation of whaterver class that implements OncePerRequestFilter, in my particular case I created an implementation of AuthenticationFilter.

Using Tomcat to prevent concurrent User session from same PC

I have looked at a few good examples on SO here such as
How to Prevent Concurrent User Logins in PHP/MySQL Site?
and they describe the problem I'm trying solve. Basically only allow a given user to open One and Only one session at a time, be it from the same PC or 2 different PCs.
So querying a DB for a LoggedIN/Not LoggedIN flag is the simplest workable solution.
How to implement this is my problem.
Having session validation added to each page which gets run each time the page is requested is not workable as it would require modifying all our JSPs ( Long story but we don't have a common Header file )
Is there any way I can reconfigure Tomcat to run some validation checks on each request to query the DB ? Maybe using valves or some other means? I don't have a lot of Tomcat experience so this is why I ask.
Thnx
Instead of changing all your JSP files, you can look at using a Filter. The filter will allow you to intercept the requests and perform some level of validation on the request.
Then however you decide to check for active sessions is up to you.
public class SessionCheckFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
//Your validation code here.
boolean returnValue = YourClass.performSessionValidation();
if(returnValue){
//Do Something
}else{
//Do Something else
}
//standard filter call
chain.doFilter(req, res);
}
And then in the web.xml map the servlet to your code. (change according to your needs)
<filter>
<filter-name>SessionCheckFilter</filter-name>
<filter-class>com.stackoverflow.SessionCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionCheckFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
For more information see the servlet-filter info page here on SO

Resources