Spring Security: Access to the currently authenticated user inside the servlet. Filter

I recently started learning about Spring Security, and today I stepped on this basic (I believe) question: why can't I access the current Principal inside the Servlet filter, as shown in the following class:

package com.acme.test; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; @Component public class TestFilter implements Filter { /* * (non-Javadoc) * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SecurityContext securityContext = SecurityContextHolder.getContext(); Authentication auth = securityContext.getAuthentication(); // auth is null here chain.doFilter(request, response); } /* * (non-Javadoc) * * @see javax.servlet.Filter#destroy() */ @Override public void destroy() { // TODO Auto-generated method stub } } 

Authentication object obtained using authentication auth = securityContext.getAuthentication (); zero. Although using the above snippet inside MVC @Controller works just fine (as expected).

Why is this happening?

+8
spring spring-mvc spring-security servlets
source share
4 answers

inside doFilter :

 HttpServletRequest request = (HttpServletRequest) request; HttpSession session = request.getSession(false); SecurityContextImpl sci = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT"); if (sci != null) { UserDetails cud = (UserDetails) sci.getAuthentication().getPrincipal(); // do whatever you need here with the UserDetails } 

Hope this helps

+16
source share

The following snippet works and provides an instance of Principal :

 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; Principal principal = req.getUserPrincipal(); if (principal != null) { // do something with the Principal } chain.doFilter(request, response); } 
+3
source share

You can see here that in order to access the SecurityContext, the security filter must be the first.

If you ask how to do this, it depends on how you configure your web application. In my case, I use Spring-Boot based on the Servlet-3 configuration style and Spring context configuration in Java (without XML) So, my configuration looks like this:

 @Configuration @EnableWebMvc @EnableWebMvcSecurity public class WebCtxConfig extends WebMvcConfigurerAdapter { @Autowired ApplicationContext ctx; @Bean FilterRegistrationBean springSecurityFilter() { FilterChainProxy o = (FilterChainProxy) ctx .getBean(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); FilterRegistrationBean trVal = new FilterRegistrationBean(); trVal.setFilter(o); trVal.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE + 1); return trVal; } @Bean public FilterRegistrationBean applicationContextIdFilter(final IThreadLifecycleManager threadLifecycleManager) { FilterRegistrationBean retVal = new FilterRegistrationBean(); YourFilter filter = new YourFilter(); retVal.setFilter(filter); retVal.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE + 2); return retVal; } } 

Note that by setting the order, you can control the order of the filters.

+2
source share

A good old web.xml deployment descriptor is an easy way to determine the order of the filters. From the Servlet 3.0 specification: the order used by the container when creating a filter chain to apply to a specific request URI is as follows:

  • First, matching matching filters in the same order as these items appear in the deployment descriptor.
  • Then the corresponding filter mappings in the same order as these items appear in the deployment descriptor.

In short, you must place the <filter-mapping> filter for the filter after it is protected by Spring.

Also from the same specification document: if the order in which listeners, servlets, filters are called is important, you must use a deployment descriptor.

+2
source share

All Articles