or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication-filters.mdauthorization.mdcsrf-protection.mdfilter-chain.mdfirewall.mdindex.mdlogout.mdreactive-security.mdrequest-matching.mdsaved-requests.mdsecurity-context.mdsecurity-headers.mdservlet-integration.mdsession-management.md
tile.json

saved-requests.mddocs/

Saved Requests

Saved requests cache the original request destination so users can be redirected after authentication.

Request Cache

RequestCache

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);
}

HttpSessionRequestCache

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);
}

NullRequestCache

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);
}

CookieRequestCache

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);
}

Saved Request

SavedRequest

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();
}

DefaultSavedRequest

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();
}

SimpleSavedRequest

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();
}

SavedCookie

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();
}

Request Cache Filter

RequestCacheAwareFilter

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;
}

Usage Examples

Basic Request Cache Configuration

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;
    }
}

Selective Request Caching

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;
}

Disabling Request Cache (Stateless)

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();
    }
}