Spring Security Web module provides comprehensive security services and servlet integration for web applications built with the Spring Framework
Saved requests cache the original request destination so users can be redirected after authentication.
Interface for caching and retrieving saved requests.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public interface RequestCache {
/**
* Saves the current request for later retrieval.
*
* @param request the HTTP request
* @param response the HTTP response
*/
void saveRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Returns the saved request.
*
* @param request the current request
* @param response the current response
* @return the saved request or null
*/
SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Returns a request that matches the saved request.
*
* @param request the current request
* @param response the current response
* @return the matching request or null
*/
HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Removes the saved request.
*
* @param request the current request
* @param response the current response
*/
void removeRequest(HttpServletRequest request, HttpServletResponse response);
}Stores saved requests in the HTTP session.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.web.util.matcher.RequestMatcher;
public class HttpSessionRequestCache implements RequestCache {
public static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST";
public HttpSessionRequestCache();
public void saveRequest(HttpServletRequest request, HttpServletResponse response);
public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response);
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response);
public void removeRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Sets matcher for requests that should be cached.
* Default: caches non-GET requests only.
*/
public void setRequestMatcher(RequestMatcher requestMatcher);
/**
* Sets the session attribute name (default: SPRING_SECURITY_SAVED_REQUEST).
*/
public void setSessionAttrName(String sessionAttrName);
/**
* Sets whether to allow session creation (default: true).
*/
public void setCreateSessionAllowed(boolean createSessionAllowed);
/**
* Sets the port resolver for scheme-relative URLs.
*/
public void setPortResolver(PortResolver portResolver);
}A RequestCache that does not save requests (for stateless applications).
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class NullRequestCache implements RequestCache {
public NullRequestCache();
public void saveRequest(HttpServletRequest request, HttpServletResponse response);
public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response);
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response);
public void removeRequest(HttpServletRequest request, HttpServletResponse response);
}Stores saved requests in a cookie instead of the session.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class CookieRequestCache implements RequestCache {
/**
* Creates a cookie-based request cache.
*/
public CookieRequestCache();
public void saveRequest(HttpServletRequest request, HttpServletResponse response);
public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response);
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response);
public void removeRequest(HttpServletRequest request, HttpServletResponse response);
/**
* Sets the matcher for requests that should be cached.
*/
public void setRequestMatcher(RequestMatcher requestMatcher);
/**
* Sets the cookie name for storing the saved request.
* Default: "REDIRECT_URI"
*/
public void setCookieName(String cookieName);
/**
* Sets the cookie max age in seconds.
* Default: -1 (session cookie)
*/
public void setCookieMaxAge(int cookieMaxAge);
/**
* Sets whether the cookie should be secure (HTTPS only).
*/
public void setCookieSecure(boolean cookieSecure);
/**
* Sets whether the cookie should be HTTP-only.
* Default: true
*/
public void setCookieHttpOnly(boolean cookieHttpOnly);
/**
* Sets the cookie domain.
*/
public void setCookieDomain(String cookieDomain);
/**
* Sets the cookie path.
* Default: "/"
*/
public void setCookiePath(String cookiePath);
}Represents a cached HTTP request.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.Cookie;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public interface SavedRequest {
/**
* Returns the URL to redirect to.
*/
String getRedirectUrl();
/**
* Returns the cookies from the saved request.
*/
List<Cookie> getCookies();
/**
* Returns the HTTP method.
*/
String getMethod();
/**
* Returns header values for the given name.
*/
List<String> getHeaderValues(String name);
/**
* Returns all header names.
*/
Collection<String> getHeaderNames();
/**
* Returns the locales from the request.
*/
List<Locale> getLocales();
/**
* Returns parameter values for the given name.
*/
String[] getParameterValues(String name);
/**
* Returns all parameters.
*/
Map<String, String[]> getParameterMap();
}Default implementation of SavedRequest.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class DefaultSavedRequest implements SavedRequest {
/**
* Creates a saved request from the HttpServletRequest.
*/
public DefaultSavedRequest(HttpServletRequest request, PortResolver portResolver);
public String getRedirectUrl();
public List<Cookie> getCookies();
public String getMethod();
public List<String> getHeaderValues(String name);
public Collection<String> getHeaderNames();
public List<Locale> getLocales();
public String[] getParameterValues(String name);
public Map<String, String[]> getParameterMap();
public String getContextPath();
public String getQueryString();
public String getRequestURI();
public String getRequestURL();
public String getScheme();
public String getServerName();
public int getServerPort();
public String getServletPath();
}Simplified implementation of SavedRequest (Since 4.0).
package org.springframework.security.web.savedrequest;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class SimpleSavedRequest implements SavedRequest {
/**
* Creates a simple saved request.
*
* @param redirectUrl the URL to redirect to
* @since 4.0
*/
public SimpleSavedRequest(String redirectUrl);
/**
* Creates a simple saved request from another saved request.
*
* @param request the saved request to copy from
* @since 4.0
*/
public SimpleSavedRequest(SavedRequest request);
public String getRedirectUrl();
public List<SavedCookie> getCookies();
public String getMethod();
public List<String> getHeaderValues(String name);
public Collection<String> getHeaderNames();
public List<Locale> getLocales();
public String[] getParameterValues(String name);
public Map<String, String[]> getParameterMap();
}Represents a saved HTTP cookie.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.http.Cookie;
public class SavedCookie {
/**
* Creates a saved cookie from an HTTP cookie.
*
* @param cookie the HTTP cookie
*/
public SavedCookie(Cookie cookie);
/**
* Creates a saved cookie with the given parameters.
*
* @param name the cookie name
* @param value the cookie value
* @param comment the cookie comment
* @param domain the cookie domain
* @param maxAge the cookie max age
* @param path the cookie path
* @param secure whether the cookie is secure
* @param version the cookie version
*/
public SavedCookie(String name, String value, String comment, String domain,
int maxAge, String path, boolean secure, int version);
public String getName();
public String getValue();
public String getComment();
public String getDomain();
public int getMaxAge();
public String getPath();
public boolean isSecure();
public int getVersion();
/**
* Converts to a Jakarta Servlet Cookie.
*
* @return the cookie
*/
public Cookie getCookie();
}Filter that replaces the request with a saved request if one exists.
package org.springframework.security.web.savedrequest;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import java.io.IOException;
import org.springframework.web.filter.GenericFilterBean;
public class RequestCacheAwareFilter extends GenericFilterBean {
/**
* Creates a filter with the given request cache.
*/
public RequestCacheAwareFilter(RequestCache requestCache);
/**
* Creates a filter with default HttpSessionRequestCache.
*/
public RequestCacheAwareFilter();
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
}import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
@Configuration
public class RequestCacheConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, RequestCache requestCache)
throws Exception {
http
.requestCache(cache -> cache
.requestCache(requestCache)
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
return http.build();
}
@Bean
public RequestCache requestCache() {
HttpSessionRequestCache cache = new HttpSessionRequestCache();
cache.setCreateSessionAllowed(true);
return cache;
}
}import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
@Bean
public RequestCache requestCache() {
HttpSessionRequestCache cache = new HttpSessionRequestCache();
// Only cache requests to protected resources, not public ones
cache.setRequestMatcher(
new NegatedRequestMatcher(
PathPatternRequestMatcher.pathPattern("/public/**")
)
);
return cache;
}import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.savedrequest.NullRequestCache;
@Configuration
public class StatelessConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.requestCache(cache -> cache
.requestCache(new NullRequestCache())
);
return http.build();
}
}Install with Tessl CLI
npx tessl i tessl/maven-spring-security-web