Applying order to OpenEntityManagerInView possible? - spring

I am using OpenEntityManagerInView in my application, so that EntityManager is open and closed automatically as per the request lifecycle. Also, I have one filter in my application that is responsible for providing authentication via interacting with DB.
#Component
public class AuthFilter extends OncePerRequestFilter {
#Autowired
IAuthService service;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException {
/*doing auth stuff here:
*service.validateUser(payload);
*responsible for opening and closing em
*/
filterChain.doFilter(servletRequest, response);
}
}
Since this filter is talking with DB, it's opening EntityManager during its operation and closing after it is done(automatically due to #Transactional annotation).
After successful authentication, it's calling other filters if any in the chain.
The challenge which I am facing is OpenEntityManagerInViewInterceptor is called after the above filter is done with its authentication, which in turn is leading to the session being open and closed two times per request, first on auth filter and second on OpenEntityManagerInView
How can I make OpenEntityManagerInViewInterceptor being called before all the filters specified in the application, so that filter can use already open EntityManager for DB operations(if req)
Tried #Order(Ordered.LOWEST_PRECEDENCE) above filter, but didn't worked

You can only configure the order of servlet filters through a web.xml
Also see https://stackoverflow.com/a/6561816/412446

Related

Servlet filter applied twice

I have an spring boot application exposing rest endpoints, inside the project there is a library that applies a filter:
#Component
#Order(1)
public class MyFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {}
It works fine, but there is a weird behavior I found. whenever my library(the one with the filter) makes a remote call to another rest service(i do it to evaluate certain logic based on the response), when that service returns a response, before returning, the filter is applied again, and of course, I do not want this behavior.
I am 100% certain this is what causes the 2nd call to the filter because if I omit the rest call, the filter is applied only once.
why are you doing "internal rest requests" ? instead of calling directly the underlying service?
use a FilterRegistrationBean
#Bean
public FilterRegistrationBean<MyFilter> loggingFilter(){
FilterRegistrationBean<MyFilter> registrationBean
= new FilterRegistrationBean<>();
registrationBean.setFilter(new MyFilter());
registrationBean.addUrlPatterns("/users/*");
return registrationBean;
}

configuring interceptors to perform "pre-tasks" on hitting endpoints in spring based web app

I am required to perform some pre-task whenever few specific endpoints are hit in my spring based web app. I came across the interceptor component provided by the spring-security framework. I searched various forums but didn't find relevant answers for configuring and adding interceptor.
Consider a situation where I am required to set some key=value in a database by sending POST request in the database whenever the user hits following endpoints.
/endpoint1
/endpoint2
/endpoint3
/endpoint4
After completion of the pre-task user should be redirected to the origin endpoint.
How can this be achieved using an interceptor in the spring-security framework?
Spring Security is for security stuff related to Authentification and Authorization. You can trigger some action if somebody logged in, but if you just need to trigger action for each request than Spring Security is not a good place for that (according to business logic), better add just filter. Anyway answering to your question:
The best way is to add custom filter to Spring Security Filter Chain:
You have to overwrite:
#Configuration
public class CustomWebSecurityConfigurerAdapter
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(
new CustomFilter(), BasicAuthenticationFilter.class);
}
}
and create your custom filter:
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//your logic here
chain.doFilter(request, response); //it's needed to pass your request father
}
}
Code taken from baeldung.com see for more information

How to create servlet filter to authorize the request?

How to create spring servlet filter to authorize the request.
Need to add a filter in the spring security filter chain that updates the user with few details (re-loading permissions or anything) for every request, if they need to be changed.
Need some sample code snippet to follow or understand.
Thanks in advance.
To add a custom filter you should extend the org.springframework.web.filter.GenericFilterBean, like so:
public class MySecurityFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
The next step is to actually register the filter by overriding the configure method of WebSecurityConfigurerAdapter:
#Configuration
public class CustomWebSecurityConfigurerAdapter
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(
new MySecurityFilter(), BasicAuthenticationFilter.class);
}
}
As you can see the filter is added by adding the filter to the HttpSecurity object. The method that is used is the addFilterAfter which basically allocates your filter after the one that you provide in the second argument, in this example is the BasicAuthenticationFilter, so your filter will be executed after this one, in the spring secuirty chain of filters.
Update
Refer to this link to personalize the authorization of your servlet. The method gives you an Authentication object, through which you can obtain your User object and perform additional checks.

Spring security shares context between multiple threads, how can I avoid this?

I have been working on a spring-based service, using JWT for authentication.
The service handling the user requests calls an authorization service in a filter which sets up the security context and looks pretty much like this :
#Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {
private final Logger log = LoggerFactory.getLogger(this.getClass());
#Autowired
private AuthorizationServiceClient authorizationServiceClient;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
User user = authorizationServiceClient.requestUserFromToken(request.getHeader("X-Auth-Token"));
SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user));
filterChain.doFilter(request, response);
SecurityContextHolder.getContext().setAuthentication(null);
} catch (HttpClientErrorException e) {
response.sendError(e.getStatusCode().value());
}
}
}
The AuthorizationServiceClient calls a remote service which handles the validation of the user's role and credentials.
I have been facing a very strange behavior :
When a page on my UI was making multiple request simultaneously, I end up getting a 500, caused by a NullPointerException.
The root cause is the Principal (containing the identity of the user) being null, when it shouldn't have.
After a painful investigation, I ended figuring that the SecurityContextHolder, even though it was using a ThreadLocal, was using sessions, and then would be shared between the threads.
The SecurityContextHolder.getContext().setAuthentication(null); was erasing the value used in concurrent threads when some requests were made in the same session, and was leading to the NPE.
So, if like me, you'd like to prevent the use of the sessions, you need to set up the security using :
http.
[...]
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).
[...]

Call a bean AFTER successful spring security login?

If I have spring security working, how can I have it call a bean to initialize all my user data once it has logged in? I can do a Servlet Filter but it calls that on every request. I want to just call some init code to load some user data into the session after the user logs in.
When the user logs in correctly spring security call an instance of AuthenticationSuccessHandler. What you want to do is create your own bean and use that to perform whatever extra actions you want.
Your class would probably look something like this:
public class YourAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//do whatever you want
super.onAuthenticationSuccess(request, response, authentication);
}
}
Also register your class as a spring bean
<beans:bean id="authenticationSuccessHandler"
class="your.package.YourAuthenticationSuccessHandler"/>
and add it to the form login security configuration as the value of authentication-success-handler-ref

Resources