Spring Security dengan banyak Configuration
Tags: indonesia, java, springboot, springsecurity
Published: 2021-10-16 03:26:29

---
tags:
  - indonesia
  - java
  - springboot
  - springsecurity
---

## tl;dr
- letakan configuration pada satu class.
- perhatikan urutan configuration karena spring security tidak bersifat exhaustive.
- gunakan `@Order` untuk mengurutkan konfigurasi
- Untuk melihat code yang sudah selesai bisa langsung cek akhir halaman.

kali ini saya ingin membagikan cara untuk konfigurasi spring security agar mendukung dua jenis authentication contoh jwt dan form based authentication. tetapi kali ini untuk mempermudah penjelasan saya akan menggunakan basic dan form based authentication. 

pertama kita membuat dua class yang `extends` dari `WebSecurityConfigurerAdapter` yaitu `FormSecurityConfig` dan `BasicSecurityConfig`.

```java
public class FormSecurityConfig extends WebSecurityConfigurerAdapter {}

public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {}
```

pada setiap class kita lakukan konfiguarsi untuk basic dan form based authentication yaitu dengan cara melakukan `override` method `cofigure`.

```java
public class FormSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/dashboard/**").formLogin();
        }
}

public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.httpBasic();
        }
}
```

buat satu class untuk menampung kedua konfigurasi. _**Spring Security tidak memeriksa semua konfigurasi oleh karena itu urutan konfigurasi sangat berpengaruh**_, saran saya letakan konfigurasi spesifik pada awal dan konfigurasi umum pada akhir. Gunakan `@Order` untuk melakukan pengurutan.

```java
public class SecurityConfig {
    @Order(1)
    public class FormSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/dashboard/**").formLogin();
        }
    }

    @Order(2)
    public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.httpBasic();
        }
    }
}
```

setelah itu selesaikan konfigurasi seperti biasa, dibawah salah satu contoh code yang sudah selesai.

```java
@EnableWebSecurity
public class SecurityConfig {

    private final UserPrincipalDetailService userPrincipalDetailService;

    public SecurityConfig(UserPrincipalDetailService userPrincipalDetailService) {
        this.userPrincipalDetailService = userPrincipalDetailService;
    }

    @Bean
    DaoAuthenticationProvider daoAuthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userPrincipalDetailService);

        return daoAuthenticationProvider;
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Order(1)
    @Configuration
    public static class FormSecurityConfig extends WebSecurityConfigurerAdapter {

        private final DaoAuthenticationProvider daoAuthenticationProvider;

        public FormSecurityConfig(DaoAuthenticationProvider daoAuthenticationProvider) {
            this.daoAuthenticationProvider = daoAuthenticationProvider;
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) {
            auth.authenticationProvider(daoAuthenticationProvider);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/dashboard/**")
                    .authorizeRequests()
                    .antMatchers("/dashboard").authenticated()
                    .antMatchers("/dashboard/admin").hasAuthority("ROLE_ADMIN")
                    .antMatchers("/dashboard/user").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
                    .and()

                    .formLogin()
                    .usernameParameter("username")
                    .passwordParameter("password")
                    .loginPage("/dashboard/login")
                    .loginProcessingUrl("/dashboard/login")
                    .permitAll()
                    .and()

                    .logout()
                    .logoutUrl("/dashboard/logout")
                    .logoutSuccessUrl("/dashboard/login")
                    .and()

                    .rememberMe()
                    .rememberMeParameter("remember-me")
                    .tokenValiditySeconds(2592000);
        }
    }

    @Configuration
    @Order(2)
    public static class BasicSecurityConfig extends WebSecurityConfigurerAdapter {

        private final DaoAuthenticationProvider daoAuthenticationProvider;

        public BasicSecurityConfig(DaoAuthenticationProvider daoAuthenticationProvider) {
            this.daoAuthenticationProvider = daoAuthenticationProvider;
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) {
            auth.authenticationProvider(daoAuthenticationProvider);
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                    .httpBasic();
        }
    }
}
```