[JAVA-29171] Upgrade spring-security-core module to Spring Boot 3 (#15487)
This commit is contained in:
parent
67c4875aff
commit
ff11a92e8a
|
@ -10,8 +10,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-modules</artifactId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@ -66,6 +67,10 @@
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<start-class>com.baeldung.app.App</start-class>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>live</id>
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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<String, Object> 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<String, Object> 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> authentication) {
|
||||
try {
|
||||
return authentication.get().getName();
|
||||
} catch (Exception var3) {
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
private Object getDetails(Supplier<Authentication> authentication) {
|
||||
try {
|
||||
return (authentication.get()).getDetails();
|
||||
} catch (Exception var3) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<ConfigAttribute> findAttributes(Method method, Class<?> targetClass) {
|
||||
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
|
||||
MergedAnnotations annotations = MergedAnnotations.from(method,
|
||||
MergedAnnotations.SearchStrategy.DIRECT);
|
||||
List<ConfigAttribute> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<NestedServletException>() {
|
||||
@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"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue