JAVA-29312 Upgrade spring-security-web-mvc (#15687)

Co-authored-by: timis1 <noreplay@yahoo.com>
This commit is contained in:
timis1 2024-01-20 01:03:25 +02:00 committed by GitHub
parent 699cd6e8cd
commit 1724f67a39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 153 additions and 161 deletions

View File

@ -4,7 +4,7 @@
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
/src/main/resources/templates/classes
*/META-INF/*
# Packaged files #

View File

@ -10,7 +10,8 @@
<parent>
<groupId>com.baeldung</groupId>
<artifactId>spring-security-modules</artifactId>
<artifactId>parent-boot-3</artifactId>
<relativePath>../../parent-boot-3</relativePath>
<version>0.0.1-SNAPSHOT</version>
</parent>
@ -38,11 +39,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>runtime</scope>
</dependency>
<!-- ops -->
<dependency>
<groupId>io.dropwizard.metrics</groupId>
@ -55,9 +51,16 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.version}</version>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>
</dependencies>
@ -67,7 +70,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.baeldung.SpringSessionApplication</mainClass>
<mainClass>com.baeldung.session.SpringSessionApplication</mainClass>
<layout>JAR</layout>
</configuration>
</plugin>

View File

@ -1,36 +1,34 @@
package com.baeldung.clearsitedata;
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.CACHE;
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.COOKIES;
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.STORAGE;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableMethodSecurity
public class SpringSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/homepage.html", true)
.and()
.logout()
.logoutUrl("/baeldung/logout")
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES, STORAGE)));
http.csrf(AbstractHttpConfigurer::disable)
.formLogin(httpSecurityFormLoginConfigurer ->
httpSecurityFormLoginConfigurer.loginPage("/login")
.loginProcessingUrl("/perform_login")
.defaultSuccessUrl("/homepage", true))
.logout(httpSecurityLogoutConfigurer ->
httpSecurityLogoutConfigurer.logoutUrl("/baeldung/logout")
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES, STORAGE))));
return http.build();
}
}

View File

@ -3,9 +3,9 @@ package com.baeldung.security;
import java.io.IOException;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -61,9 +61,9 @@ public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSu
}
if (isUser) {
return "/homepage.html";
return "/homepage";
} else if (isAdmin) {
return "/console.html";
return "/console";
} else {
throw new IllegalStateException();
}

View File

@ -3,15 +3,15 @@ package com.baeldung.session.filter;
import java.io.IOException;
import java.util.Arrays;
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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class SessionFilter implements Filter{

View File

@ -3,6 +3,7 @@ package com.baeldung.session.security.config;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@ -11,7 +12,9 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.session.HttpSessionEventPublisher;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
import com.baeldung.security.MySimpleUrlAuthenticationSuccessHandler;
@ -35,37 +38,28 @@ public class SecSecurityConfig {
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/anonymous*")
.anonymous()
.antMatchers("/login*", "/invalidSession*", "/sessionExpired*", "/foo/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.successHandler(successHandler())
.failureUrl("/login.html?error=true")
.and()
.logout()
.deleteCookies("JSESSIONID")
.and()
.rememberMe()
.key("uniqueAndSecret")
.tokenValiditySeconds(86400)
.and()
.sessionManagement()
.sessionFixation()
.migrateSession()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/invalidSession.html")
.maximumSessions(2)
.expiredUrl("/sessionExpired.html");
public SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry ->
authorizationManagerRequestMatcherRegistry
.requestMatchers(mvc.pattern("/anonymous*")).anonymous()
.requestMatchers(mvc.pattern("/login*"), mvc.pattern("/invalidSession*"), mvc.pattern("/sessionExpired*"),
mvc.pattern("/foo/**")).permitAll()
.anyRequest().authenticated())
.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.loginPage("/login")
.loginProcessingUrl("/login")
.successHandler(successHandler())
.failureUrl("/login?error=true"))
.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.deleteCookies("JSESSIONID"))
.rememberMe(httpSecurityRememberMeConfigurer ->
httpSecurityRememberMeConfigurer.key("uniqueAndSecret")
.tokenValiditySeconds(86400))
.sessionManagement(httpSecuritySessionManagementConfigurer ->
httpSecuritySessionManagementConfigurer.sessionFixation()
.migrateSession().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/invalidSession")
.maximumSessions(2)
.expiredUrl("/sessionExpired"));
return http.build();
}
@ -83,4 +77,8 @@ public class SecSecurityConfig {
return new BCryptPasswordEncoder();
}
@Bean
MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector);
}
}

View File

@ -1,6 +1,6 @@
package com.baeldung.session.web;
import javax.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;

View File

@ -1,6 +1,6 @@
package com.baeldung.session.web;
import javax.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -1,14 +1,13 @@
package com.baeldung.session.web.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import jakarta.servlet.ServletContext;
import org.springframework.web.WebApplicationInitializer;
public class MainWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext sc) throws ServletException {
public void onStartup(ServletContext sc) {
sc.getSessionCookieConfig().setHttpOnly(true);
sc.getSessionCookieConfig().setSecure(true);
}

View File

@ -9,13 +9,13 @@ public class MvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/anonymous.html");
registry.addViewController("/anonymous").setViewName("view/anonymous");
registry.addViewController("/login.html");
registry.addViewController("/homepage.html");
registry.addViewController("/sessionExpired.html");
registry.addViewController("/invalidSession.html");
registry.addViewController("/console.html");
registry.addViewController("/login").setViewName("view/login");
registry.addViewController("/homepage").setViewName("view/homepage");
registry.addViewController("/sessionExpired").setViewName("view/sessionExpired");
registry.addViewController("/invalidSession").setViewName("view/invalidSession");
registry.addViewController("/console").setViewName("view/console");
}
@ -27,7 +27,8 @@ public class MvcConfig implements WebMvcConfigurer {
// final InternalResourceViewResolver bean = new InternalResourceViewResolver();
//
// bean.setViewClass(JstlView.class);
// bean.setPrefix("/WEB-INF/view/");
// bean.setPrefix("/templates/view/");
// bean.setSuffix(".jsp");
// return bean;
// }
}

View File

@ -2,8 +2,8 @@ package com.baeldung.web;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
import com.baeldung.monitoring.MetricRegistrySingleton;
import com.codahale.metrics.Counter;

View File

@ -0,0 +1,9 @@
<html>
<head></head>
<body>
<h1>Anonymous page</h1>
<a href="/login"/>To Login</a>
</body>
</html>

View File

@ -0,0 +1,20 @@
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head></head>
<body>
<h1>This is the landing page for the admin</h1>
<div sec:authorize="hasRole('ROLE_USER')">
This text is only visible to a user
<br/>
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
This text is only visible to an admin
<br/>
</div>
<a href="/logout" />Logout</a>
</body>
</html>

View File

@ -0,0 +1,20 @@
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head></head>
<body>
<h1>This is the homepage for the user</h1>
<div sec:authorize="hasRole('ROLE_USER')">
This text is only visible to a user
<br />
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
This text is only visible to an admin
<br />
</div>
<a href="/logout" />Logout</a>
</body>
</html>

View File

@ -0,0 +1,9 @@
<html>
<head></head>
<body>
<h1>Invalid Session Page</h1>
<a href="/login"/>To Login</a>
</body>
</html>

View File

@ -0,0 +1,9 @@
<html>
<head></head>
<body>
<h1>Session Expired Page</h1>
<a href="/login" />To Login</a>
</body>
</html>

View File

@ -1,10 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head></head>
<body>
<h1>Anonymous page</h1>
<a href="<c:url value="/login.html" />">To Login</a>
</body>
</html>

View File

@ -1,22 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<html>
<head></head>
<body>
<h1>This is the landing page for the admin</h1>
<security:authorize access="hasRole('ROLE_USER')">
This text is only visible to a user
<br/>
</security:authorize>
<security:authorize access="hasRole('ROLE_ADMIN')">
This text is only visible to an admin
<br/>
</security:authorize>
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

View File

@ -1,22 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
<html>
<head></head>
<body>
<h1>This is the homepage for the user</h1>
<security:authorize access="hasRole('ROLE_USER')">
This text is only visible to a user
<br />
</security:authorize>
<security:authorize access="hasRole('ROLE_ADMIN')">
This text is only visible to an admin
<br />
</security:authorize>
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

View File

@ -1,10 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head></head>
<body>
<h1>Invalid Session Page</h1>
<a href="<c:url value="/login.html" />">To Login</a>
</body>
</html>

View File

@ -1,10 +0,0 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head></head>
<body>
<h1>Session Expired Page</h1>
<a href="<c:url value="/login.html" />">To Login</a>
</body>
</html>

View File

@ -13,7 +13,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import javax.servlet.Filter;
import jakarta.servlet.Filter;
@ExtendWith(SpringExtension.class)
@WebAppConfiguration

View File

@ -35,11 +35,11 @@ public class SessionConfigurationLiveTest {
Response resp3 = simpleResponseRequestUsingSessionNotFollowingRedirects(sessionFilter);
assertThat(resp3.getStatusCode()).isEqualTo(HttpStatus.FOUND.value());
assertThat(resp3.getHeader("Location")).isEqualTo("http://localhost:8080/invalidSession.html");
assertThat(resp3.getHeader("Location")).isEqualTo("http://localhost:8080/invalidSession");
}
@Test
public void givenValidUser_whenLoginMoreThanMaxValidSession_thenRedirectedToExpiredSessionUri() throws Exception {
public void givenValidUser_whenLoginMoreThanMaxValidSession_thenRedirectedToExpiredSessionUri() {
SessionFilter sessionFilter = new SessionFilter();
simpleSvcRequestLoggingIn(sessionFilter);
simpleSvcRequestLoggingIn();
@ -56,7 +56,7 @@ public class SessionConfigurationLiveTest {
.get(SESSION_SVC_URL);
assertThat(resp4.getStatusCode()).isEqualTo(HttpStatus.FOUND.value());
assertThat(resp4.getHeader("Location")).isEqualTo("http://localhost:8080/sessionExpired.html");
assertThat(resp4.getHeader("Location")).isEqualTo("http://localhost:8080/sessionExpired");
}
private static void simpleSvcRequestLoggingIn() {