Notice
I wrote this article and was originally published on Qiita on 16 September 2019.
Interface org.springframework.security.config.annotation.ObjectPostProcessor
On Spring Security configurer/builder, they are designed for to accept one or more instance contains ObjectPostProcessor interface. Below is the definition.
public interface ObjectPostProcessor<T> {
  <O extends T> O postProcess(O object);
}
postProcess() method is for alter instance which pass into it.
There is a ObjectPostProcessor implementation class: org.springframework.security.config.annotation.configuration.AutowireBeanFactoryObjectPostProcessor. The job of this class
- initialized instance (including inject prerequisite instance by using ApplicationContext) which passed into it
- it call SmartInitializingSingleton, DisposableBean interface methods of instance which processed before when same methods being called from ApplicationContext against it
A singleton instance of AutowireBeanFactoryObjectPostProcessor bean is created and be inject into configurer/builder when created. (This is the first ObjectPostProcessor if that configurer/builder accepts more than one ObjectPostProcessor)
Some configurer/builder can accept more than one ObjectPostProcessor. So alter instance which built from these configurer/builder is possible.
Example
First get a copy of my notice board example application. Add below file into info.saladlam.example.spring.noticeboard.support package.
package info.saladlam.example.spring.noticeboard.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.config.annotation.ObjectPostProcessor;
public class CustomizeObjectPostProcessor implements ObjectPostProcessor<Object> {
    private static final Logger log = LoggerFactory.getLogger(CustomizeObjectPostProcessor.class);
    private String fromClass;
    public CustomizeObjectPostProcessor(String fromClass) {
        this.fromClass = fromClass;
    }
    public <T> T postProcess(T object) {
        log.info("Instance pass into {}: {}", this.fromClass, object.getClass().getName());
        return object;
    }
}
Then alter configure() method in class info.saladlam.example.spring.noticeboard.config.WebSecurityConfig to following.
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // must put more restricted rule at first
                .antMatchers("/manage/*/approve").hasAuthority("ADMIN")
                .antMatchers("/manage/**").hasAuthority("USER")
            .and()
                .httpBasic().disable()
                .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/loginHandler")
                    .failureUrl("/login?error=true")
                    .permitAll()
            .and()
                .logout().logoutSuccessUrl("/");
        http.authorizeRequests().withObjectPostProcessor(new CustomizeObjectPostProcessor("authorizeRequests"));
        http.formLogin().addObjectPostProcessor(new CustomizeObjectPostProcessor("formLogin"));
        http.httpBasic().addObjectPostProcessor(new CustomizeObjectPostProcessor("httpBasic"));
        http.logout().addObjectPostProcessor(new CustomizeObjectPostProcessor("logout"));
    }
Finally you may see following in log message.
2019-09-16 12:25:54.503  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into formLogin: org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
2019-09-16 12:25:56.121  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into httpBasic: org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint
2019-09-16 12:25:57.009  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into httpBasic: org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler
2019-09-16 12:25:58.145  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into logout: org.springframework.security.web.authentication.logout.LogoutFilter
2019-09-16 12:25:59.732  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into authorizeRequests: org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
2019-09-16 12:26:00.798  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into authorizeRequests: org.springframework.security.access.vote.AffirmativeBased
2019-09-16 12:29:01.005  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into authorizeRequests: org.springframework.security.web.access.intercept.FilterSecurityInterceptor
2019-09-16 12:29:03.527  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into formLogin: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
2019-09-16 12:29:03.933  INFO 5512 --- [  restartedMain] i.s.e.s.n.s.CustomizeObjectPostProcessor : Instance pass into httpBasic: org.springframework.security.web.authentication.www.BasicAuthenticationFilter
By designs CustomizeObjectPostProcessor class, you may alter instance pass into it.
Appendix: list of class instance created by Spring Security configurer/builder
| Spring Security configurer/builder | Class instance built | 
|---|---|
| org.springframework.security.config.annotation.authentication.configurers.provisioning.JdbcUserDetailsManagerConfigurer | org.springframework.security.authentication.dao.DaoAuthenticationProvider | 
| org.springframework.security.config.annotation.web.configurers.CsrfConfigurer | org.springframework.security.web.csrf.CsrfFilter | 
| org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer | org.springframework.security.web.access.ExceptionTranslationFilter | 
| org.springframework.security.config.annotation.web.configurers.HeadersConfigurer | org.springframework.security.web.header.HeaderWriterFilter | 
| org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer | org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy, org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy, org.springframework.security.web.session.SessionManagementFilter | 
| org.springframework.security.config.annotation.web.configurers.SecurityContextConfigurer | org.springframework.security.web.context.SecurityContextPersistenceFilter | 
| org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer | org.springframework.security.web.savedrequest.RequestCacheAwareFilter | 
| org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer | org.springframework.security.authentication.AnonymousAuthenticationProvider | 
| org.springframework.security.config.annotation.web.configurers.ServletApiConfigurer | org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter | 
| org.springframework.security.config.annotation.web.configurers.LogoutConfigurer | org.springframework.security.web.authentication.logout.LogoutFilter | 
| org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer | org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler, org.springframework.security.access.vote.AffirmativeBasedorg.springframework.security.web.access.intercept.FilterSecurityInterceptor | 
| org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer | org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter | 
 

 
    
Top comments (0)