Spring Security authentication, authorization and hierarchical authorities configuration.
Subpages
Manual authentication, custom authorization w/ OAuth & hierarchical authorities configuration (Spring Boot)
Manual authentication, custom authorization w/ JWT & hierarchical authorities configuration (Spring Boot)
https://docs.spring.io/spring-security/reference/servlet/authorization/authorize-http-requests.html
Remark: hasRole('ROLE_ADMIN') ~ hasRole(‘ADMIN') because the ‘ROLE_‘ prefix gets added automatically.
hasRole('ADMIN')
hasAnyRole('ADMIN','USER')
Remark: hasAuthority('ROLE_ADMIN') ~ hasRole('ROLE_ADMIN')
hasAuthority("ADMIN")
hasAnyAuthority("ADMIN", "USER")
permitAll() // both anonymous and logged in
denyAll()
isAnonymous()
isAuthenticated()
isRememberMe() // Rember Me functionality using cookies
isFullyAuthenticated() // If the user isn't an anonymous or remember-me user
Expressions that, respectively, allow to access the principal object representing the current authorized (or anonymous) user and the current Authentication object from the SecurityContext.
It allows to specify authorization constraints on individual domain objects based on abstract permissions.
hasPermission(Object target, Object permission)
hasPermission(Object targetId, String targetType, Object permission)
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
WebSecurityConfig
package edu.uoc.gpradoc;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.firewall.StrictHttpFirewall;
import jakarta.inject.Inject;
/**
* Note: Order lower values have higher priority. Higher values will only execute if no adapter with
* lower value matches.
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
/** Data REST base path */
private String basePathDataRest;
/**
* Constructor
*
* @param basePathDataRest -
*
*/
@Inject
public WebSecurityConfig(
@Value("${spring.data.rest.base-path:'/merida'}") String basePathDataRest) {
super();
this.basePathDataRest = basePathDataRest;
}
/**
* Configuration for allowing special characters, e.g: ';', '\', '/' and '%'.
* @return -
*/
@Bean
WebSecurityCustomizer webSecurityCustomizer() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
// symbol '/' encoded '%2F' [didn't work w/ sb-3.1.3 (uses Tomcat-10.1.12)]
firewall.setAllowUrlEncodedSlash(true);
// symbol '\'
firewall.setAllowBackSlash(true);
// symbol ';'
firewall.setAllowSemicolon(true);
// symbol '%'
firewall.setAllowUrlEncodedPercent(true);
return web -> web.httpFirewall(firewall);
}
/**
* @param http
* @return -
* @throws Exception
*/
@Order(4)
@Bean
SecurityFilterChain filterChain4(HttpSecurity http) throws Exception {
/*- DOC:
* Default user and pass is configured in application.properties (spring.security.user.*).
*/
http// sb3
.securityMatcher(basePathDataRest + "/**") // Apply only if match
.authorizeHttpRequests(authorize -> authorize//
.anyRequest().authenticated() //
)//
.httpBasic(basic -> basic.realmName("GPRA_docback"))//
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//
;
return http.build();
}
/**
* @param http
* @return -
* @throws Exception
*/
@Order(5)
@Bean
SecurityFilterChain filterChain5(HttpSecurity http) throws Exception {
/*- DOC:
* Default user and pass is configured in application.properties (spring.security.user.*).
*/
http// sb3
.securityMatcher("/actuator", "/actuator/**") // Apply only if match
.authorizeHttpRequests(authorize -> authorize//
.anyRequest().authenticated() //
)//
.httpBasic().realmName("GPRA_docback")//
.and()//
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//
;
return http.build();
}
/**
* Springdoc v2 (for Spring Boot >= 3.0).
*
* @param http
* @return -
* @throws Exception
*/
@SuppressWarnings({"java:S1612"})
@Order(6)
@Bean
SecurityFilterChain filterChainSpringDocV2(HttpSecurity http) throws Exception {
final String[] pathAnonymous = // NOSONAR (SONARJAVA-3991)
{ "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**" };
http// sb3
.securityMatcher(pathAnonymous) // only invoke if matching
.authorizeHttpRequests(authorize -> authorize//
.anyRequest().anonymous()//
) //
;
http.csrf(csrf -> csrf.disable())//
.headers(headers -> headers.frameOptions(fo -> fo.disable()));//
// DOC. Avoid generation of cookie JSESSIONID (Swagger)
http.sessionManagement(sm ->
sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
/**
* Other anonymous.
*
* @param http
* @return -
* @throws Exception
*/
@Order(7)
@Bean
SecurityFilterChain filterChainOtherAnonymous(HttpSecurity http) throws Exception {
final String[] pathAnonymous = { "/ui/**", "/monitor/**", "/tech/**", "/favicon*", "/version", "/csrf" };
http// sb3
.securityMatcher(pathAnonymous) // Apply only if match
.authorizeHttpRequests(authorize -> authorize//
.anyRequest().anonymous()//
) //
;
http.csrf().disable();
http.headers().frameOptions().disable();
// DOC. Avoid generation of cookie JSESSIONID (Swagger)
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
return http.build();
}
}