Skip to content

Latest commit

 

History

History
206 lines (148 loc) · 18.1 KB

spring-security.md

File metadata and controls

206 lines (148 loc) · 18.1 KB

Spring Security in detail

Initial step:

Steps to configure web MVC by adding dependencies explicitly without Spring Boot auto-configure -

  1. Add dependencies

  2. Extend AbstractAnnotationConfigDispatcherServletInitializer, then add implementation for all the methods -

    • Provide a configuration class for the getServletConfigClasses method with the custom config class.
    • Provide URL mapping for the getServletMapping method.
  3. In the custom config class should be marked with @Configuration, @EnableWebMvc and @ComponentScan annotations. Also, this class should create a bean for the view resolver if the view page exists in the project folder location. (create InternalResourceViewresolver bean).

Adding Spring Security -

Before the dispatcher dispatches the request Spring security filter comes in the action to filter the requests. It is just a simple servlet filter.

  1. Add dependencies

  2. Create a custom web security class for your application by extending WebSecurityConfigurerAdapter and mark this class with @EnableWebSecurity, then this custom web security should be attached with Spring security using custom security initializer.

  3. To create custom security initializer extend AbstractSecurityWebApplicationInitializer

  4. With respect to the custom web security class in the step 2 inherit method configure(HttpSecurity http) which contains default behaviour to authenticate form based and rest client. This can be overridden by the custom authentication mechanism. This method is used to configure all the endpoints and authorization.

  5. Override configure(AuthenticationManagerBuilder auth) to authenticate the user based upon requirement, here we can configure different types of authentication such as in-memory/jdbc/ldap etc.

Note -

Spring Security basic architecture

Spring Security Flow

Authentication Manager Flow

  • Default and form-based authentication create UsernamePasswordAuthenticationToken object which is of the Authentication type.

  • There are different types of Spring-provided filters, one of the filters is UsernamePasswordAuthenticationFilter which makes requests to the implementation of the AuthenticationManager interface for all the configured AuthenticationProvider implementations.

  • Filters in the spring can be configured in different ways, here are two simple approaches -

    1. Extending the existing Spring provided filter and override the doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) E.g OncePerRequestFilter

      public class CustomFilter extends OncePerRequestFilter {
          @Override
          protected void doFilterInternal(HttpServletRequest request, 
              HttpServletResponse response, FilterChain filterChain)
              throws ServletException, IOException {
              /**
              *  Custom logic can be here.
              */   
              filterChain.doFilter(request, response);
          }
      }
      
    2. Implementing javax.servlet.Filter and override the doFilter(ServletRequest request, ServletResponse response, FilterChain chain) method, but it needs to be configured in the custom SecurityConfig class.

      public class CustomFilter implements Filter {
          @Override
          protected void doFilter(ServletRequest request, 
              ServletResponse response, FilterChain chain)
              throws IOException, ServletException {
              /**
              *  Custom logic can be here.
              */   
              chain.doFilter(request, response);
          }
      }
      
      
      @EnableWebSecurity
      public class SecurityConfig {
      
          @Bean
          protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
              return http
                  .addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
                  .requestMatchers().antMatchers("/home").and().csrf().disable()
                  .authorizeRequests().anyRequest().permitAll()
                  .and().build();
          }
      }
      
  • The default behavior of UsernamePasswordAuthenticationFilter for the form-based login, this class extends AbstractAuthenticationProcessingFilter that extends GenericFilterBean and GenericFilterBean implements javax.servlet.Filter. UsernamePasswordAuthenticationFilter overrides attemptAuthentication(HttpServletRequest request, HttpServletResponse response) and it creates default UsernamePasswordAuthenticationToken object that is indirectly Authentication type. Below is the reference

AttemptAuthentication implementation in the UsernamePasswordAuthenticationFilter class

  • AuthenticationProvider in the spring can be configured in different ways. Following are the steps to configure a custom authentication provider :

    1. Create a custom filter to register a custom authentication type. The filter should extends AbstractAuthenticationProcessingFilter and override attemptAuthentication(HttpServletRequest request, HttpServletResponse response) method then return the custom type authentication object and this custom type authentication object should be of type org.springframework.security.core.Authentication.

      public class CustomAuthenticationType implements org.springframework.security.core.Authentication {
      
      }
      
      public class CustomFilter extends AbstractAuthenticationProcessingFilter {
      
          protected CustomFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
              super(requiresAuthenticationRequestMatcher);
          }
      
          @Override
          public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                  throws AuthenticationException, IOException, ServletException {
              /**
              *  Custom logic can be here.
              */ 
              CustomAuthenticationType customAuthenticationType = new CustomAuthenticationType();
              return this.getAuthenticationManager().authenticate(customAuthenticationType);
          }
      }
      
    2. Create a custom authentication provider by implementing AuthenticationProvider. Among two of the overridden method the supports(Class<?> authentication) method let spring know whether to execute a custom authentication provider or not.

      @Component
      public class CustomAuthenticationProviderImpl implements AuthenticationProvider {
      
          @Override
          public Authentication authenticate(Authentication authentication) throws AuthenticationException {
              /**
               * This is just a sample code and will have some core logic
               */
              return new CustomAuthenticationType();
          }
      
          @Override
          public boolean supports(Class<?> authentication) {
              return authentication.equals(CustomAuthenticationType.class);
          }
      }
      
    3. Add custom authentication provider in the custom SecurityConfig class.

      @EnableWebSecurity
      public class SecurityConfig {
          
          @Autowired
          private CustomAuthenticationProviderImpl customAuthenticationProviderImpl;
          
          @Bean
          protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
              return http
                  .authenticationProvider(customAuthenticationProviderImpl)
                  .addFilterAfter(new CustomFilter(), UsernamePasswordAuthenticationFilter.class)
                  .requestMatchers().antMatchers("/home").and().csrf().disable()
                  .authorizeRequests().anyRequest().permitAll()
                  .and().build();
          }
      }
      
    4. Spring ProviderManager scan thru all the registered authentication provider and then execute that authentication mechanism. This check is done in the overridden authenticate(Authentication authentication) method of the AuthenticationManager interface.

      ProviderManager scans registered authentication mechanism

Spring Security after successful authentication

Spring security basic flow chart

Spring security flow chart