Spring SecurityContext in Async Controller Response - spring

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?

Related

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

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 !!!

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).

Async feature in Servlets

I was just going back to Servlet-3.x features and exploring it. If I am not wrong, before Servlet-3.x it was thread per request model and it would run out of threads in the pool, for heavy incoming traffic.
So, with Servlet-3.x it says it is Asynchronous and doesn't keep the threads blocked , rather releases them immediately but just the task is delegated.
Here is my interpretation,
consider there are 2 threads in Server thread-pool
For a new Async Servlet request R1 there is a thread T1, this T1 would delegate the task to T2 and T1 responds back to client immediately.
Question: Is T2 created from Server thread-pool? If so, I don't get the point.
Case 1: If it was old Synchronous Servlet request T1 would have been busy running I/O task,
Case 2: If it was Asynchronous Servlet call T2 is busy running I/O task.
In both cases, one of them is busy.
I tried to check the same with a sample Async servlet in openliberty app server, below is the sample log captured from my sample demo Servlet.
Entering doGet() == thread name is = Default Executor-thread-116
Exiting doGet() == thread name is = Default Executor-thread-116
=== Long running task started ===
Thread executing #start of long running task = Default Executor-thread-54
Thread executing #end of long running task = Default Executor-thread-54
=== Long running task ended ===
As shown above, the Default Executor-thread-116 is released immediately and delegated long running task to the Default Executor-thread-54, but I am not sure if they are from the App Server thread pool. If so, why can't just Default Executor-thread-116 do the task instead of delegation?
Can someone throw some light on this async behavior of Servlets in JavaEE
In your example, where the work is synchronous and there's no separate executor/threadpool, there is nearly no point to use async servlets. Lots of samples/examples out there are just block on a 2nd thread because they're trying to illustrate just the syntax.
But there's no reason why you can't spin off a thread to do a little work, add your async context to some list, and then after some event (inbound JMS, websocket, whatever) provides the data needed to complete the async response. For example, a 2-player game server wouldn't wait for player 2 in a second thread, it would just have their async context floating around in memory waiting for a 2nd player to find it.

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.

MassTransit fault consumer not invoked for request/response

What is the best practice for handling exceptions in MassTransit 3+ with regard to Request/Response pattern? The docs here mention that if a ResponseAddress exists on a message, the Fault message will be sent to that address, but how does one consumer/receive the messages at that address? The ResponseAddress for Bus.Request seems to be an auto-generated MassTransit address that I don't have control over, so I don't know how to access the exception thrown in the main consumer. What am I missing? Here's my code to register the consumer and its fault consumer using Unity container:
cfg.ReceiveEndpoint(host, "request_response_queue", e =>
{
e.Consumer<IConsumer<IRequestResponse>>(container);
e.Consumer(() => container.Resolve<IMessageFaultConsumer<IRequestResponse>>() as IConsumer<Fault<IRequestResponse>>);
});
And here's my attempt at a global message fault consumer:
public interface IMessageFaultConsumer<TMessage>
{
}
public class MessageFaultConsumer<TMessage> : IConsumer<Fault<TMessage>>, IMessageFaultConsumer<TMessage>
{
public Task Consume(ConsumeContext<Fault<TMessage>> context)
{
Console.WriteLine("MessageFaultConsumer");
return Task.FromResult(0);
}
}
This approach DOES work when I use Bus.Publish as opposed to Bus.Request. I also looked into creating an IConsumeObserver and putting my global exception logging code into the ConsumeFault method, but that has the downside of being invoked every exception prior to the re-tries giving up. What is the proper way to handle exceptions for request/response?
First of all, the request/response support in MassTransit is meant to be used with the .Request() method, or the request client (MessageRequestClient or PublishRequestClient). With these methods, if the consumer of the request message throws an exception, that exception is packaged into the Fault<T>, which is sent to the ResponseAddress. Since the .Request() method, and the request client are both asynchronous, using await will throw an exception with the exception data from the fault included. That's how it is designed, await the request and it will either complete, timeout, or fault (throw an exception upon await).
If you are trying to put in some global "exception handler" code for logging purposes, you really should log those at the service boundary, and an observer is the best way to handle it. This way, you can just implement the ConsumeFault method, and log to your event sink. However, this is synchronous within the consumer pipeline, so recognize the delay that could be introduced.
The other option is to of course just consume Fault<T>, but as you mentioned, it does not get published when the request client is used with the response address in the header. In this case, perhaps your requester should publish an event indicating that operation X faulted, and you can log that -- at the business context level versus the service level.
There are many options here, it's just choosing the one that fits your use case best.

Resources