diff --git a/spring-security-modules/spring-security-core/pom.xml b/spring-security-modules/spring-security-core/pom.xml index 2a18145ac0..d9a5445eee 100644 --- a/spring-security-modules/spring-security-core/pom.xml +++ b/spring-security-modules/spring-security-core/pom.xml @@ -10,8 +10,9 @@ com.baeldung - spring-security-modules + parent-boot-3 0.0.1-SNAPSHOT + ../../parent-boot-3 @@ -66,6 +67,10 @@ + + com.baeldung.app.App + + live diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/App.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/App.java index 6e41a53967..3d0e09d9ed 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/App.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/App.java @@ -1,13 +1,10 @@ package com.baeldung.app; -import javax.servlet.Filter; +import jakarta.servlet.Filter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.web.filter.DelegatingFilterProxy; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; @@ -20,7 +17,7 @@ public class App extends SpringBootServletInitializer { public static class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override - protected javax.servlet.Filter[] getServletFilters() { + protected Filter[] getServletFilters() { DelegatingFilterProxy delegateFilterProxy = new DelegatingFilterProxy(); delegateFilterProxy.setTargetBeanName("loggingFilter"); return new Filter[] { delegateFilterProxy }; diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/auditing/ExposeAttemptedPathAuthorizationAuditListener.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/auditing/ExposeAttemptedPathAuthorizationAuditListener.java index d238c157df..ff53b3cc6a 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/auditing/ExposeAttemptedPathAuthorizationAuditListener.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/auditing/ExposeAttemptedPathAuthorizationAuditListener.java @@ -2,13 +2,14 @@ package com.baeldung.app.auditing; import org.springframework.boot.actuate.audit.AuditEvent; import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener; -import org.springframework.security.access.event.AbstractAuthorizationEvent; -import org.springframework.security.access.event.AuthorizationFailureEvent; -import org.springframework.security.web.FilterInvocation; +import org.springframework.security.authorization.event.AuthorizationDeniedEvent; +import org.springframework.security.authorization.event.AuthorizationEvent; +import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.function.Supplier; @Component public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAuthorizationAuditListener { @@ -16,21 +17,37 @@ public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAutho public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE"; @Override - public void onApplicationEvent(AbstractAuthorizationEvent event) { - if (event instanceof AuthorizationFailureEvent) { - onAuthorizationFailureEvent((AuthorizationFailureEvent) event); + public void onApplicationEvent(AuthorizationEvent event) { + if (event instanceof AuthorizationDeniedEvent) { + onAuthorizationFailureEvent((AuthorizationDeniedEvent) event); } } - private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) { - Map data = new HashMap<>(); - data.put("type", event.getAccessDeniedException().getClass().getName()); - data.put("message", event.getAccessDeniedException().getMessage()); - data.put("requestUrl", ((FilterInvocation)event.getSource()).getRequestUrl() ); - if (event.getAuthentication().getDetails() != null) { - data.put("details", event.getAuthentication().getDetails()); + private void onAuthorizationFailureEvent(AuthorizationDeniedEvent event) { + String name = this.getName(event.getAuthentication()); + Map data = new LinkedHashMap(); + Object details = this.getDetails(event.getAuthentication()); + if (details != null) { + data.put("details", details); } - publish(new AuditEvent(event.getAuthentication().getName(), AUTHORIZATION_FAILURE, - data)); + + publish(new AuditEvent(name, "AUTHORIZATION_FAILURE", data)); } + + private String getName(Supplier authentication) { + try { + return authentication.get().getName(); + } catch (Exception var3) { + return ""; + } + } + + private Object getDetails(Supplier authentication) { + try { + return (authentication.get()).getDetails(); + } catch (Exception var3) { + return null; + } + } + } diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java index 34de9c1e23..24f7dc8a5b 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/config/WebSecurityConfig.java @@ -2,6 +2,7 @@ package com.baeldung.app.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -18,18 +19,14 @@ public class WebSecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers("/css/**", "/js/**", "/loggedout") - .permitAll() - .anyRequest() - .authenticated() - .and() - .httpBasic() - .and() - .logout() - .disable() - .csrf() - .disable(); + http.authorizeHttpRequests(auth -> auth + .requestMatchers("/css/**", "/js/**", "/loggedout") + .permitAll() + .anyRequest() + .authenticated()) + .httpBasic(Customizer.withDefaults()) + .logout(logout -> logout.disable()) + .csrf(csrf -> csrf.disable()); return http.build(); } diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java index 7e6b2c3d9c..f2d479d782 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/controller/TaskController.java @@ -1,23 +1,14 @@ package com.baeldung.app.controller; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - import com.baeldung.app.entity.Task; import com.baeldung.app.service.TaskService; - -import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("api/tasks") diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/entity/Task.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/entity/Task.java index d2a8a1383d..b93654a19a 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/entity/Task.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/entity/Task.java @@ -1,8 +1,8 @@ package com.baeldung.app.entity; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; @Entity public class Task { diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/filter/CustomFilter.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/filter/CustomFilter.java index 7229e4606f..c16202976b 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/filter/CustomFilter.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/app/filter/CustomFilter.java @@ -1,19 +1,13 @@ package com.baeldung.app.filter; -import java.io.IOException; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; +import java.io.IOException; + @Component("loggingFilter") public class CustomFilter implements Filter { @@ -24,7 +18,7 @@ public class CustomFilter implements Filter { } @Override - public void doFilter(ServletRequest request, ServletResponse response, + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; LOGGER.info("Request Info : " + req); diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java index 3092e94c7f..585c527706 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/checkrolejava/UserController.java @@ -1,5 +1,6 @@ package com.baeldung.checkrolejava; +import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; @@ -10,7 +11,6 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import javax.servlet.http.HttpServletRequest; @Controller public class UserController { diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/denyonmissing/CustomPermissionAllowedMethodSecurityMetadataSource.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/denyonmissing/CustomPermissionAllowedMethodSecurityMetadataSource.java index 4bde3f5aa3..c6508f0ab3 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/denyonmissing/CustomPermissionAllowedMethodSecurityMetadataSource.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/denyonmissing/CustomPermissionAllowedMethodSecurityMetadataSource.java @@ -9,6 +9,8 @@ import java.util.Collection; import java.util.List; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotations; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource; import org.springframework.security.access.prepost.PostAuthorize; @@ -23,22 +25,20 @@ public class CustomPermissionAllowedMethodSecurityMetadataSource extends Abstrac @Override protected Collection findAttributes(Method method, Class targetClass) { - Annotation[] annotations = AnnotationUtils.getAnnotations(method); + MergedAnnotations annotations = MergedAnnotations.from(method, + MergedAnnotations.SearchStrategy.DIRECT); List attributes = new ArrayList<>(); + MergedAnnotations classAnnotations = MergedAnnotations.from(targetClass, MergedAnnotations.SearchStrategy.DIRECT); // if the class is annotated as @Controller we should by default deny access to every method - if (AnnotationUtils.findAnnotation(targetClass, Controller.class) != null) { + if (classAnnotations.get(Controller.class).isPresent()) { attributes.add(DENY_ALL_ATTRIBUTE); } - if (annotations != null) { - for (Annotation a : annotations) { - // but not if the method has at least a PreAuthorize or PostAuthorize annotation - if (a instanceof PreAuthorize || a instanceof PostAuthorize) { - return null; - } - } + if (annotations.get(PreAuthorize.class).isPresent() || annotations.get(PostAuthorize.class).isPresent()) { + return null; } + return attributes; } diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/filterresponse/config/AppConfig.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/filterresponse/config/AppConfig.java index 439468f365..d57c1f2e5f 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/filterresponse/config/AppConfig.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/filterresponse/config/AppConfig.java @@ -3,6 +3,7 @@ package com.baeldung.filterresponse.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; @@ -37,13 +38,11 @@ public class AppConfig implements WebMvcConfigurer { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf() - .disable() - .authorizeRequests() - .anyRequest() - .authenticated() - .and() - .httpBasic(); + http.authorizeHttpRequests(auth -> auth + .anyRequest() + .authenticated()) + .httpBasic(Customizer.withDefaults()) + .csrf(csrf -> csrf.disable()); return http.build(); } diff --git a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/methodsecurity/service/UserRoleService.java b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/methodsecurity/service/UserRoleService.java index 1579044700..88914d1507 100644 --- a/spring-security-modules/spring-security-core/src/main/java/com/baeldung/methodsecurity/service/UserRoleService.java +++ b/spring-security-modules/spring-security-core/src/main/java/com/baeldung/methodsecurity/service/UserRoleService.java @@ -1,10 +1,9 @@ package com.baeldung.methodsecurity.service; -import java.util.List; -import java.util.stream.Collectors; - -import javax.annotation.security.RolesAllowed; - +import com.baeldung.methodsecurity.annotation.IsViewer; +import com.baeldung.methodsecurity.entity.CustomUser; +import com.baeldung.methodsecurity.repository.UserRoleRepository; +import jakarta.annotation.security.RolesAllowed; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.annotation.Secured; import org.springframework.security.access.prepost.PostAuthorize; @@ -15,9 +14,8 @@ import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import com.baeldung.methodsecurity.annotation.IsViewer; -import com.baeldung.methodsecurity.entity.CustomUser; -import com.baeldung.methodsecurity.repository.UserRoleRepository; +import java.util.List; +import java.util.stream.Collectors; @Service public class UserRoleService { diff --git a/spring-security-modules/spring-security-core/src/test/java/com/baeldung/denyonmissing/DenyOnMissingControllerIntegrationTest.java b/spring-security-modules/spring-security-core/src/test/java/com/baeldung/denyonmissing/DenyOnMissingControllerIntegrationTest.java index b4e4154982..2f67168229 100644 --- a/spring-security-modules/spring-security-core/src/test/java/com/baeldung/denyonmissing/DenyOnMissingControllerIntegrationTest.java +++ b/spring-security-modules/spring-security-core/src/test/java/com/baeldung/denyonmissing/DenyOnMissingControllerIntegrationTest.java @@ -1,14 +1,9 @@ package com.baeldung.denyonmissing; -import static org.hamcrest.core.Is.isA; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - +import jakarta.servlet.ServletException; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -19,12 +14,13 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = DenyApplication.class) public class DenyOnMissingControllerIntegrationTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Autowired private WebApplicationContext context; private MockMvc mockMvc; @@ -46,8 +42,11 @@ public class DenyOnMissingControllerIntegrationTest { @Test @WithMockUser(username = "user") public void givenANormalUser_whenCallingBye_thenAccessDenied() throws Exception { - expectedException.expectCause(isA(AccessDeniedException.class)); + ServletException exception = Assertions.assertThrows(ServletException.class, () -> { + mockMvc.perform(get("/bye")); + }); - mockMvc.perform(get("/bye")); + Assertions.assertNotNull(exception); + Assertions.assertEquals(exception.getCause().getClass(), AccessDeniedException.class); } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-core/src/test/java/com/baeldung/filterresponse/SpringSecurityJsonViewIntegrationTest.java b/spring-security-modules/spring-security-core/src/test/java/com/baeldung/filterresponse/SpringSecurityJsonViewIntegrationTest.java index fc821b5175..fd80ae48c9 100644 --- a/spring-security-modules/spring-security-core/src/test/java/com/baeldung/filterresponse/SpringSecurityJsonViewIntegrationTest.java +++ b/spring-security-modules/spring-security-core/src/test/java/com/baeldung/filterresponse/SpringSecurityJsonViewIntegrationTest.java @@ -1,12 +1,10 @@ package com.baeldung.filterresponse; import com.baeldung.filterresponse.config.AppConfig; -import org.hamcrest.BaseMatcher; -import org.hamcrest.Description; +import jakarta.servlet.ServletException; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.test.context.support.WithMockUser; @@ -16,8 +14,8 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.util.NestedServletException; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -32,9 +30,6 @@ public class SpringSecurityJsonViewIntegrationTest { private MockMvc mvc; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void setup() { mvc = MockMvcBuilders @@ -65,21 +60,12 @@ public class SpringSecurityJsonViewIntegrationTest { @Test @WithMockUser(username = "user", password = "userPass", roles = {"ADMIN", "USER"}) public void whenMultipleRoles_thenExceptionIsThrown() throws Exception { - expectedException.expect(new BaseMatcher() { - @Override - public boolean matches(Object o) { - NestedServletException exception = (NestedServletException) o; - return exception.getCause() instanceof IllegalArgumentException && exception.getCause().getMessage().equals("Ambiguous @JsonView declaration for roles ROLE_ADMIN,ROLE_USER"); - } - - @Override - public void describeTo(Description description) { - - } + ServletException exception = Assertions.assertThrows(ServletException.class, () -> { + mvc.perform(get("/items")) + .andExpect(status().isOk()); }); - mvc.perform(get("/items")) - .andExpect(status().isOk()); - + Assertions.assertEquals(exception.getCause().getClass(), IllegalArgumentException.class); + assertTrue(exception.getCause().getMessage().equals("Ambiguous @JsonView declaration for roles ROLE_ADMIN,ROLE_USER")); } }