Spring Security - MacKittipat/note-developer GitHub Wiki

Spring Security

Architecture

Ref : http://shazsterblog.blogspot.com/2018/10/spring-security-authentication-security.html

Ref : https://docs.gigaspaces.com/latest/security/introducing-spring-security.html

Ref : https://springbootdev.com/2017/08/23/spring-security-authentication-architecture/

Example

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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/user").hasAnyRole("USER", "ADMIN")
                .antMatchers("/admin").hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        auth.inMemoryAuthentication()
                .withUser("mac")
                .password(bCryptPasswordEncoder.encode("password"))
                .roles("USER")
                .and()
                .withUser("admin")
                .password(bCryptPasswordEncoder.encode("password"))
                .roles("ADMIN");
    }

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

}

Explanation :

  1. Open http://localhost:8080/user, browser will redirect to /login page
  2. After enter user and pass and click login, UsernamePasswordAuthenticationFilter.attemptAuthentication() will intercept the request. It can intercept login page because there is path configuration in constructor.
public UsernamePasswordAuthenticationFilter() {
    super(new AntPathRequestMatcher("/login", "POST"));
}
  1. In UsernamePasswordAuthenticationFilter, this.getAuthenticationManager().authenticate(authRequest) will call ProviderManager.authenticate()
  2. In ProviderManager, provider.authenticate(authentication); will call DaoAuthenticationProvider.authenticate() to check username and password.

Filter

DelegatingFilterProxy use FilterChainProxy to execute filter in order from WebAsyncManagerIntegrationFilter to FilterSecurityInterceptor

Execute order

DelegatingFilterProxy.doFilter() ->

FilterChainProxy.doFilter() ->

WebAsyncManagerIntegrationFilter.doFilter() ->

SecurityContextPersistenceFilter.doFilter() ->

...

(AbstractAuthenticationProcessingFilter.doFilter() -> UsernamePasswordAuthenticationFilter.attemptAuthentication())

...

Reference