From c17e258a6fb1ebf30cc51a740f657adff5cef6da Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 26 Oct 2022 09:49:09 -0500 Subject: [PATCH 1/2] Document Saved Requests Closes gh-12088 --- .../ROOT/pages/servlet/architecture.adoc | 28 +++++++++-- .../architecture/request-cache-continue.adoc | 50 +++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 docs/modules/ROOT/partials/servlet/architecture/request-cache-continue.adoc diff --git a/docs/modules/ROOT/pages/servlet/architecture.adoc b/docs/modules/ROOT/pages/servlet/architecture.adoc index f9ca15fdeb..28f9273e1c 100644 --- a/docs/modules/ROOT/pages/servlet/architecture.adoc +++ b/docs/modules/ROOT/pages/servlet/architecture.adoc @@ -188,7 +188,7 @@ Below 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 @@ -213,8 +213,7 @@ 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. @@ -247,3 +246,26 @@ try { This means that if another part of the application, (i.e. xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`] or method security) throws an `AuthenticationException` or `AccessDeniedException` it will be caught and handled here. <2> If the user is not authenticated or it is an `AuthenticationException`, then __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 From 24cc7ff17803ae3bed1ec16396c10fc39715bbcd Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Wed, 26 Oct 2022 09:51:35 -0500 Subject: [PATCH 2/2] Document Saved Requests Migration Closes gh-12089 --- docs/modules/ROOT/pages/migration.adoc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/modules/ROOT/pages/migration.adoc b/docs/modules/ROOT/pages/migration.adoc index 0b9970a0ce..6c47392292 100644 --- a/docs/modules/ROOT/pages/migration.adoc +++ b/docs/modules/ROOT/pages/migration.adoc @@ -6,6 +6,20 @@ Use 5.8 and the steps below to minimize changes when updating to 6.0. == 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 xref:servlet/authorization/method-security.adoc[Method Security] has been xref:servlet/authorization/method-security.adoc#jc-enable-method-security[simplified] through {security-api-url}org/springframework/security/authorization/AuthorizationManager.html[the `AuthorizationManager` API] and direct use of Spring AOP.