JAVA-29312 Upgrade spring-security-web-mvc (#15687)
Co-authored-by: timis1 <noreplay@yahoo.com>
This commit is contained in:
parent
699cd6e8cd
commit
1724f67a39
|
@ -4,7 +4,7 @@
|
|||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
/src/main/resources/templates/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Anonymous page</h1>
|
||||
|
||||
<a href="/login"/>To Login</a>
|
||||
</body>
|
||||
</html>
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Invalid Session Page</h1>
|
||||
|
||||
<a href="/login"/>To Login</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Session Expired Page</h1>
|
||||
|
||||
<a href="/login" />To Login</a>
|
||||
</body>
|
||||
</html>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue