How to configure spring security 3.2 to use dao authentication and custom authentication filter using java config

StackOverflow https://stackoverflow.com/questions/21474726

Question

I have googled spring security examples using dao authentication and custom authentication filter, but which are I found, all the examples are using xml file configuration,

My question is how to configure custom filter i.e. UsernamePasswordAuthenticationFilter

my xml based securityConfig file looks like:

<http auto-config="false" use-expressions="true">

    <intercept-url pattern="/" access="permitAll" />        
    <intercept-url pattern="/auth/login.html" access="permitAll" />     
    <intercept-url pattern="/auth/logout.html" access="permitAll" />        
    <intercept-url pattern="/auth/accessDenied.html" access="permitAll" />      
    <intercept-url pattern="/admin/**" access="hasAnyRole('ROLE_ADMIN')" />
    <intercept-url pattern="/user/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />


    <access-denied-handler error-page="/auth/accessDenied.html"/>

    <form-login login-page='/auth/login.html' 
        default-target-url="/"
        authentication-success-handler-ref="myAuthenticationSuccessHandler"
        authentication-failure-url="/auth/loginfailed.html" />

    <logout success-handler-ref="myLogoutSuccessHandler"
            invalidate-session="true" delete-cookies="JSESSIONID" />

    <remember-me key="uniqueAndSecret" token-validity-seconds="86400" />

     <session-management session-fixation-protection="migrateSession" 
            session-authentication-error-url="/auth/loginfailed.html"> 
        <concurrency-control max-sessions="1" 
                error-if-maximum-exceeded="true" 
                expired-url="/auth/login.html" 
                session-registry-alias="sessionRegistry"/>
    </session-management>

</http>

<beans:bean id="myAuthenticationSuccessHandler" 
    class="com.asn.handler.AsnUrlAuthenticationSuccessHandler" />

<beans:bean id="myLogoutSuccessHandler" 
    class="com.asn.handler.AsnLogoutSuccessHandler" />

<beans:bean id="userDetailsService" class="com.asn.service.UserDetailsServiceImpl"/>

<authentication-manager alias="authenticationManager">      
    <authentication-provider user-service-ref="userDetailsService"> 
        <password-encoder ref="encoder"/>                      
    </authentication-provider>
    <!-- <authentication-provider>
        <user-service>
            <user name="user1" password="user1Pass" authorities="ROLE_USER" />
            <user name="admin1" password="admin1Pass" authorities="ROLE_ADMIN" />
        </user-service>
    </authentication-provider> -->
</authentication-manager>

<!-- For hashing and salting user passwords -->
<beans:bean id="encoder" 
        class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

I want to convert the configuration's into Java configuration based.. i have tried like this which is doesn't work:

SecurityConfig class:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder encoder;

    /*@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)throws Exception {
        logger.info("configureGlobal(AuthenticationManagerBuilder auth) invoked..");
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder);       
    }*/

    @Override
    protected void configure(HttpSecurity http) throws Exception {  
        http.csrf().disable().authorizeRequests()
            .antMatchers("/resources/**","/assets/**","/files/**").permitAll()
            .antMatchers("/auth","/").permitAll()                           

                .anyRequest().authenticated() //every request requires the user to be authenticated
                .and()
            .formLogin() //form based authentication is supported
                .loginPage("/auth/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();

        http.exceptionHandling().accessDeniedPage("/auth/accessDenied");

        http.sessionManagement().sessionFixation().migrateSession()
            .sessionAuthenticationStrategy(concunSessContAuthStr());
    }

    @Bean(name="sessionRegistry")
    public SessionRegistryImpl sessionRegistryBean(){
        logger.info("sessionRegistryBean() invoked..");
        return new SessionRegistryImpl();
    }

    @Bean
    public UsernamePasswordAuthenticationFilter authFilter() throws Exception{
        logger.info("authFilter() invoked.."); 
        CustomUsernamePasswordAuthenticationFilter upaf = new CustomUsernamePasswordAuthenticationFilter();
        upaf.setAuthenticationManager(".."); //here, how to set AuthenticationManager ??
        upaf.setSessionAuthenticationStrategy(concunSessContAuthStr());
        return upaf;
    }


    @Bean
    public DaoAuthenticationProvider customAuthenticationManagerBean() {

        DaoAuthenticationProvider dap = new DaoAuthenticationProvider();
        dap.setUserDetailsService(userDetailsService);
        dap.setPasswordEncoder(encoder);
        return dap;
    }

    @Bean
    public ConcurrentSessionControlAuthenticationStrategy concunSessContAuthStr(){
        logger.info("concunSessContAuthStr() invoked.."); 
        ConcurrentSessionControlAuthenticationStrategy cscas= new ConcurrentSessionControlAuthenticationStrategy(sessionRegistryBean());
        cscas.setMaximumSessions(2);
        cscas.setExceptionIfMaximumExceeded(true);
        return cscas;
    }

}

Any Suggestions how to configure?

Thank You!

Was it helpful?

Solution

In order to use a customized class replacing the UsernamePasswordAuthenticationFilter do the following:

  • create a new class FormLoginConfigurer with the following content (the original org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer is unfortunately final and cannot be extended), notice the call to super(new CustomAuthenticationProcessingFilter(),null):

    package demo;
    
    import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
    import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
    import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
    import org.springframework.security.web.util.matcher.RequestMatcher;
    
    public class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractAuthenticationFilterConfigurer<H,FormLoginConfigurer<H>,UsernamePasswordAuthenticationFilter> {
    
    public FormLoginConfigurer() {
        super(new CustomAuthenticationProcessingFilter(),null);
        usernameParameter("username");
        passwordParameter("password");
    }
    
    public FormLoginConfigurer<H> loginPage(String loginPage) {
        return super.loginPage(loginPage);
    }
    
    public FormLoginConfigurer<H> usernameParameter(String usernameParameter) {
        getAuthenticationFilter().setUsernameParameter(usernameParameter);
        return this;
    }
    
    public FormLoginConfigurer<H> passwordParameter(String passwordParameter) {
        getAuthenticationFilter().setPasswordParameter(passwordParameter);
        return this;
    }
    
    @Override
    public void init(H http) throws Exception {
        super.init(http);
        initDefaultLoginFilter(http);
    }
    
    @Override
    protected RequestMatcher createLoginProcessingUrlMatcher(
            String loginProcessingUrl) {
        return new AntPathRequestMatcher(loginProcessingUrl, "POST");
    }
    
    private String getUsernameParameter() {
        return getAuthenticationFilter().getUsernameParameter();
    }
    
    private String getPasswordParameter() {
        return getAuthenticationFilter().getPasswordParameter();
    }
    
    private void initDefaultLoginFilter(H http) {
        DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
        if(loginPageGeneratingFilter != null && !isCustomLoginPage()) {
            loginPageGeneratingFilter.setFormLoginEnabled(true);
            loginPageGeneratingFilter.setUsernameParameter(getUsernameParameter());
            loginPageGeneratingFilter.setPasswordParameter(getPasswordParameter());
            loginPageGeneratingFilter.setLoginPageUrl(getLoginPage());
            loginPageGeneratingFilter.setFailureUrl(getFailureUrl());
            loginPageGeneratingFilter.setAuthenticationUrl(getLoginProcessingUrl());
        }
    }
    

    }

  • remove the formLogin() call from your configure(HttpSecurity) method and use the following initialization instead:

     FormLoginConfigurer formLogin = new FormLoginConfigurer();
     http.apply(formLogin);
     formLogin.loginPage("/auth/login")
             .permitAll();
    
  • the authentication manager will be provided to your instance automatically

  • you can customize the SessionAuthenticationStrategy used in your class by calls to http.sessionManagement(), or you can add logic to your new FormLoginConfigurer which updates whatever you need

Another option is to register your CustomUsernamePasswordAuthenticationFilter filter as an additional filter:

  • in the configure(HttpSecurity http) method call:

     http.addFilter(authFilter());
    
  • make sure to configure all options of the filter manually

  • beware that system will also add another instance of the UsernamePasswordAuthenticationFilter after yours

In order to add a custom AuthenticationProvider:

  • override method configure(AuthenticationManagerBuilder auth) and add the provider:

     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.authenticationProvider(customAuthenticationManagerBean());
     }
    

OTHER TIPS

You are close !

upaf.setAuthenticationManager(".."); //here, how to set AuthenticationManager ??

The answer is :

upaf.setAuthenticationManager(authenticationManagerBean());

Also, add your Custom like this :

http
.addFilterBefore(authFilter(), UsernamePasswordAuthenticationFilter.class)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top