I'm working on a project that will that requires for users to be authenticated by a proxy on the.network. Username will be provided in a request header to my app.
Spring 5 is being used to handle requests and security.
The AbstractAuthenticationProcessingFilter has been extended with my own custom filter to grab the necessary header info.
A prototype was written using Spring Boot and it was successful.
In the Spring Web MVC version, the filter is loaded, but is not triggered.
The goal is for every page in my app to require authentication. For testing purposes the 'index' page is public, and the 'blogs' page requires elevated privilege.
Why does it work in a Spring Boot project (v2.6.1), but not in Spring Web MVC (5.x)?
Any help is appreciated.
Prototype Source Code on GitHub
And some of relevant bits of code are shown below:
WebSecurityConfig.java
package org.westwood.mvc.config;
import javax.servlet.Filter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.westwood.mvc.security.CustomAuthenticationProcessingFilter;
import org.westwood.mvc.security.CustomAuthenticationProvider;
import org.westwood.mvc.security.CustomUserDetailsService;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private CustomAuthenticationProvider customAuthenticationProvider = new CustomAuthenticationProvider();
@Bean
public UserDetailsService userDetailsService() {
return new CustomUserDetailsService();
}
@Bean
public CustomAuthenticationProvider authenticationProvider() {
if (customAuthenticationProvider == null) {
customAuthenticationProvider = new CustomAuthenticationProvider();
}
if (customAuthenticationProvider.userDetailsServiceIsNull()) {
customAuthenticationProvider.setUserDetailsService(userDetailsService());
}
return customAuthenticationProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.formLogin().disable()
.logout().disable()
.authenticationProvider(authenticationProvider())
.addFilterBefore(getFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests()
.antMatchers("/blogs").hasAuthority("ADMIN")
.anyRequest().permitAll();
}
private RequestMatcher getRequestMatchers() {
return new OrRequestMatcher(new AntPathRequestMatcher("/**"));
}
private Filter getFilter() throws Exception {
return new CustomAuthenticationProcessingFilter(getRequestMatchers(), authenticationManager());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
}
CustomAuthenticationProcessingFilter.java
package org.westwood.mvc.security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.security.web.util.matcher.RequestMatcher;
public class CustomAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
public CustomAuthenticationProcessingFilter(RequestMatcher requiresAuthenticationRequestMatcher,
AuthenticationManager authenticationManager) {
super(requiresAuthenticationRequestMatcher);
setAuthenticationManager(authenticationManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
// extract user name from request
String header = request.getHeader("REMOTE_USER");
// hard code for testing
header = "john-smith@gmail.com";
// create a token object to pass to authentication provider
PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken(header, null);
return getAuthenticationManager().authenticate(token);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
// save user principle in security context
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
}
Spring Boot is what is picking up the Spring Security Filter Chain and registering it with the container. Without Spring Boot, you need to register it yourself.
The simplest way to do this is to use Spring Security's AbstractSecurityWebApplicationInitializer
like so:
public class SpringSecurityFilterChainInitializer
extends AbstractSecurityWebApplicationInitializer {
}
AbstractSecurityWebApplicationInitializer#onStartup
registers the Spring Security filter chain for you. Tomcat will pick up this class just like it picks up the WebInitializer
in your project.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.