diff --git a/docs/modules/ROOT/pages/migration.adoc b/docs/modules/ROOT/pages/migration.adoc index 8d129adb56..6139e11efd 100644 --- a/docs/modules/ROOT/pages/migration.adoc +++ b/docs/modules/ROOT/pages/migration.adoc @@ -10,6 +10,20 @@ Also, this guide includes ways to <> behaviors and its def == Servlet +[[requestcache-query-optimization]] +=== Optimize Querying of `RequestCache` + +In Spring Security 5, the default behavior is to query the xref:servlet/architecture.adoc#savedrequests[saved request] on every request. +This means that in a typical setup, that in order to use the xref:servlet/architecture.adoc#requestcache[`RequestCache`] the `HttpSession` is queried on every request. + +In Spring Security 6, the default is that `RequestCache` will only be queried for a cached request if the HTTP parameter `continue` is defined. +This allows Spring Security to avoid unnecessarily reading the `HttpSession` with the `RequestCache`. + +In Spring Security 5 the default is to use `HttpSessionRequestCache` which will be queried for a cached request on every request. +If you are not overriding the defaults (i.e. using `NullRequestCache`), then the following configuration can be used to explicitly opt into the Spring Security 6 behavior in Spring Security 5.8: + +include::partial$servlet/architecture/request-cache-continue.adoc[] + === Use `AuthorizationManager` for Method Security There are no further migration steps for this feature. diff --git a/docs/modules/ROOT/pages/servlet/architecture.adoc b/docs/modules/ROOT/pages/servlet/architecture.adoc index 7404401c3c..01d729eb06 100644 --- a/docs/modules/ROOT/pages/servlet/architecture.adoc +++ b/docs/modules/ROOT/pages/servlet/architecture.adoc @@ -189,7 +189,7 @@ The following is a comprehensive list of Spring Security Filter ordering: * xref:servlet/authentication/passwords/digest.adoc#servlet-authentication-digest[`DigestAuthenticationFilter`] * `BearerTokenAuthenticationFilter` * xref:servlet/authentication/passwords/basic.adoc#servlet-authentication-basic[`BasicAuthenticationFilter`] -* `RequestCacheAwareFilter` +* <> * `SecurityContextHolderAwareRequestFilter` * `JaasApiIntegrationFilter` * `RememberMeAuthenticationFilter` @@ -216,8 +216,8 @@ image::{figures}/exceptiontranslationfilter.png[] * image:{icondir}/number_1.png[] First, the `ExceptionTranslationFilter` invokes `FilterChain.doFilter(request, response)` to invoke the rest of the application. * image:{icondir}/number_2.png[] If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__. ** The xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontextholder[SecurityContextHolder] is cleared out. -** The `HttpServletRequest` is saved in the {security-api-url}org/springframework/security/web/savedrequest/RequestCache.html[`RequestCache`]. -When the user successfully authenticates, the `RequestCache` is used to replay the original request. +** The `HttpServletRequest` is <> so that it can be used to replay the original request once authentication is successful. + // FIXME: add link to authentication success ** The `AuthenticationEntryPoint` is used to request credentials from the client. For example, it might redirect to a log in page or send a `WWW-Authenticate` header. @@ -252,3 +252,26 @@ This means that if another part of the application, (< If the user is not authenticated or it is an `AuthenticationException`, __Start Authentication__. <3> Otherwise, __Access Denied__ ==== + +[[savedrequests]] +== Saving Requests Between Authentication + +As illustrated in <>, when a request has no authentication and is for a resource that requires authentication, there is a need to save the request for the authenticated resource to re-request after authentication is successful. +In Spring Security this is done by saving the `HttpServletRequest` using a <> implementation. + +[[requestcache]] +=== RequestCache + +The `HttpServletRequest` is saved in the {security-api-url}org/springframework/security/web/savedrequest/RequestCache.html[`RequestCache`]. +When the user successfully authenticates, the `RequestCache` is used to replay the original request. +The <> is what uses the `RequestCache` to save the `HttpServletRequest`. + +By default, an `HttpSessionRequestCache` is used. +The code below demonstrates how to customize the `RequestCache` implementation that is used to check the `HttpSession` for a saved request if the parameter named `continue` is present. + +include::partial$servlet/architecture/request-cache-continue.adoc[] + +[[requestcacheawarefilter]] +=== RequestCacheAwareFilter + +The {security-api-url}org/springframework/security/web/savedrequest/RequestCacheAwareFilter.html[`RequestCacheAwareFilter`] uses the <> to save the `HttpServletRequest`. diff --git a/docs/modules/ROOT/partials/servlet/architecture/request-cache-continue.adoc b/docs/modules/ROOT/partials/servlet/architecture/request-cache-continue.adoc new file mode 100644 index 0000000000..bddde1ca6e --- /dev/null +++ b/docs/modules/ROOT/partials/servlet/architecture/request-cache-continue.adoc @@ -0,0 +1,50 @@ +.`RequestCache` Only Checks for Saved Requests if `continue` Parameter Present +==== +.Java +[source,java,role="primary"] +---- +@Bean +DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception { + HttpSessionRequestCache requestCache = new HttpSessionRequestCache(); + requestCache.setMatchingRequestParameterName("continue"); + http + // ... + .requestCache((cache) -> cache + .requestCache(requestCache) + ); + return http.build(); +} +---- + +.Kotlin +[source,kotlin,role="secondary"] +---- +@EnableWebSecurity +class SecurityConfig { + + @Bean + open fun springSecurity(http: HttpSecurity): SecurityFilterChain { + val httpRequestCache = HttpSessionRequestCache() + httpRequestCache.setMatchingRequestParameterName("continue") + http { + requestCache { + requestCache = httpRequestCache + } + } + return http.build() + } +} +---- + +.XML +[source,xml,role="secondary"] +---- + + + + + + +---- +==== \ No newline at end of file