DEV Community

Salad Lam
Salad Lam

Posted on

How to alter instance which built from Spring Security Configurer

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);
}
Enter fullscreen mode Exit fullscreen mode

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

  1. initialized instance (including inject prerequisite instance by using ApplicationContext) which passed into it
  2. 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;
    }

}
Enter fullscreen mode Exit fullscreen mode

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"));
    }
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)