RestSecurityConfig.java

package org.imageconverter.config.security;

import static org.springframework.http.HttpMethod.DELETE;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;

import org.imageconverter.config.filter.CsrfLoggerFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.firewall.HttpFirewall;

// https://freecontent.manning.com/five-awkward-things-about-spring-security-that-actually-make-sense/

/**
 * Project http's config.
 * 
 * @author Fernando Romulo da Silva
 */
@Configuration
public class RestSecurityConfig {

    private final String[] swaggerUiURL = { //
	    "/v3/api-docs/**", //
	    "/swagger-ui/**", //
	    "/swagger-ui.html", //
	    "/webjars/**" //
    };

    private final RestAuthenticationSuccessHandler authenticationSuccessHandler;

    private final HttpFirewall allowUrlEncodedSlashHttpFirewall;

    private final CsrfTokenRepository csrfTokenRepository;

    RestSecurityConfig( //
		    final RestAuthenticationSuccessHandler authenticationSuccessHandler, //
		    final HttpFirewall allowUrlEncodedSlashHttpFirewall, //
//		    final CsrfTokenRepository httpSessionCsrfTokenRepository
		    final CsrfTokenRepository cookieCsrfTokenRepository
		    ) {
	//
	this.authenticationSuccessHandler = authenticationSuccessHandler;
	this.allowUrlEncodedSlashHttpFirewall = allowUrlEncodedSlashHttpFirewall;
	this.csrfTokenRepository = cookieCsrfTokenRepository;
//	this.csrfTokenRepository = httpSessionCsrfTokenRepository;
    }

    @Bean
    SecurityFilterChain filterChain(final HttpSecurity http) throws Exception { // NOPMD - Filter throw it

	final var restUrl = "/rest/**";

	http.addFilterAfter(new CsrfLoggerFilter(), CsrfFilter.class) //
			.securityContext() //
			.and().exceptionHandling() //
			.and().servletApi() //
			.and().httpBasic() //
			//
			.and().authorizeRequests() //
			//
			/*--*/.antMatchers(swaggerUiURL) //
			/*------*/.permitAll()
			//
			/*--*/.antMatchers(GET, restUrl) // /rest/images/type
			/*------*/.hasAnyRole("USER") // , "GUEST"
			//
			/*--*/.antMatchers(POST, restUrl) //
			/*------*/.hasRole("USER") //
			//
//			/*--*/.antMatchers("/actuator/**")
//			/*------*/.hasRole("ADMIN") 			
			//
			/*--*/.antMatchers(DELETE, restUrl) //
			/*------*/.access("hasRole('ROLE_ADMIN') or hasIpAddress('127.0.0.1') or hasIpAddress('0:0:0:0:0:0:0:1')") //
			//
			/*--*/.antMatchers(restUrl) //
			/*------*/.hasAnyRole("ADMIN", "USER")
			//
			.and().formLogin() // disable redirect
			/*------*/.successHandler(authenticationSuccessHandler) //
			/*------*/.failureHandler(new SimpleUrlAuthenticationFailureHandler()) //
			//
			.and().logout() //
			/*------*/.logoutSuccessUrl("/") //
			/*------*/.invalidateHttpSession(true)//
			/*------*/.clearAuthentication(true)//
			//
			.and().csrf() //
//			/*------*/.disable() //
			/*------*/.csrfTokenRepository(csrfTokenRepository)//
			/*------*/.ignoringAntMatchers("/actuator/**")
			;

	http.headers().frameOptions().sameOrigin();

	return http.build();
    }

    @Bean
    WebSecurityCustomizer webSecurityCustomizer() {
	return (web) -> {
	    web.httpFirewall(allowUrlEncodedSlashHttpFirewall);
	};
    }
}