Extract ExceptionTranslationFilter Docs

Closes gh-8002
This commit is contained in:
Rob Winch 2020-02-20 14:38:30 -06:00
parent 32ee30e8a1
commit 6b0891b081
4 changed files with 56 additions and 38 deletions

View File

@ -3,34 +3,8 @@
There are some key filters which will always be used in a web application which uses Spring Security, so we'll look at these and their supporting classes and interfaces first. There are some key filters which will always be used in a web application which uses Spring Security, so we'll look at these and their supporting classes and interfaces first.
We won't cover every feature, so be sure to look at the Javadoc for them if you want to get the complete picture. We won't cover every feature, so be sure to look at the Javadoc for them if you want to get the complete picture.
[[exception-translation-filter]]
=== ExceptionTranslationFilter
The `ExceptionTranslationFilter` sits above the `FilterSecurityInterceptor` in the security filter stack.
It doesn't do any actual security enforcement itself, but handles exceptions thrown by the security interceptors and provides suitable and HTTP responses.
[source,xml]
----
<bean id="exceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
<property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</bean>
<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="accessDeniedHandler"
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.htm"/>
</bean>
----
[[auth-entry-point]] [[auth-entry-point]]
==== AuthenticationEntryPoint === AuthenticationEntryPoint
The `AuthenticationEntryPoint` will be called if the user requests a secure HTTP resource but they are not authenticated. The `AuthenticationEntryPoint` will be called if the user requests a secure HTTP resource but they are not authenticated.
An appropriate `AuthenticationException` or `AccessDeniedException` will be thrown by a security interceptor further down the call stack, triggering the `commence` method on the entry point. An appropriate `AuthenticationException` or `AccessDeniedException` will be thrown by a security interceptor further down the call stack, triggering the `commence` method on the entry point.
This does the job of presenting the appropriate response to the user so that authentication can begin. This does the job of presenting the appropriate response to the user so that authentication can begin.
@ -39,7 +13,7 @@ The actual implementation used will depend on the authentication mechanism you w
[[access-denied-handler]] [[access-denied-handler]]
==== AccessDeniedHandler === AccessDeniedHandler
What happens if a user is already authenticated and they try to access a protected resource? In normal usage, this shouldn't happen because the application workflow should be restricted to operations to which a user has access. What happens if a user is already authenticated and they try to access a protected resource? In normal usage, this shouldn't happen because the application workflow should be restricted to operations to which a user has access.
For example, an HTML link to an administration page might be hidden from users who do not have an admin role. For example, an HTML link to an administration page might be hidden from users who do not have an admin role.
You can't rely on hiding links for security though, as there's always a possibility that a user will just enter the URL directly in an attempt to bypass the restrictions. You can't rely on hiding links for security though, as there's always a possibility that a user will just enter the URL directly in an attempt to bypass the restrictions.
@ -62,7 +36,7 @@ See <<nsa-access-denied-handler,the namespace appendix>> for more details.
[[request-caching]] [[request-caching]]
==== SavedRequest s and the RequestCache Interface === SavedRequest s and the RequestCache Interface
Another responsibility of `ExceptionTranslationFilter` responsibilities is to save the current request before invoking the `AuthenticationEntryPoint`. Another responsibility of `ExceptionTranslationFilter` responsibilities is to save the current request before invoking the `AuthenticationEntryPoint`.
This allows the request to be restored after the user has authenticated (see previous overview of <<tech-intro-web-authentication,web authentication>>). This allows the request to be restored after the user has authenticated (see previous overview of <<tech-intro-web-authentication,web authentication>>).
A typical example would be where the user logs in with a form, and is then redirected to the original URL by the default `SavedRequestAwareAuthenticationSuccessHandler` (see <<form-login-flow-handling,below>>). A typical example would be where the user logs in with a form, and is then redirected to the original URL by the default `SavedRequestAwareAuthenticationSuccessHandler` (see <<form-login-flow-handling,below>>).

View File

@ -0,0 +1,50 @@
[[servlet-exceptiontranslationfilter]]
= Handling Security Exceptions
:figures: images/servlet/architecture
:icondir: images/icons
The {security-api-url}org/springframework/security/web/access/ExceptionTranslationFilter.html[`ExceptionTranslationFilter`] allows translation of {security-api-url}org/springframework/security/access/AccessDeniedException.html[`AccessDeniedException`] and {security-api-url}/org/springframework/security/core/AuthenticationException.html[`AuthenticationException`] into HTTP responses.
`ExceptionTranslationFilter` is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
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 <<servlet-authentication-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.
// 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.
// FIXME: link to AuthenticationEntryPoint
* image:{icondir}/number_3.png[] Otherwise if it is an `AccessDeniedException`, then __Access Denied__.
The `AccessDeniedHandler` is invoked to handle access denied.
// FIXME: link to AccessDeniedHandler
[NOTE]
====
If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, then `ExceptionTranslationFilter` does not do anything.
====
The pseudocode for `ExceptionTranslationFilter` looks something like this:
.ExceptionTranslationFilter pseudocode
[source,java]
----
try {
filterChain.doFilter(request, response); // <1>
} catch (AccessDeniedException | AuthenticationException e) {
if (!authenticated || e instanceof AuthenticationException) {
startAuthentication(); // <2>
} else {
accessDenied(); // <3>
}
}
----
<1> You will recall from <<servlet-filters-review>> that invoking `FilterChain.doFilter(request, response)` is the equivalent of invoking the rest of the application.
This means that if another part of the application, (i.e. <<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__

View File

@ -161,10 +161,12 @@ Below is a comprehensive list of Spring Security Filter ordering:
* AnonymousAuthenticationFilter * AnonymousAuthenticationFilter
* OAuth2AuthorizationCodeGrantFilter * OAuth2AuthorizationCodeGrantFilter
* SessionManagementFilter * SessionManagementFilter
* ExceptionTranslationFilter * <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>>
* <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>> * <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>>
* SwitchUserFilter * SwitchUserFilter
include::exception-translation-filter.adoc[leveloffset=+1]
include::technical-overview.adoc[] include::technical-overview.adoc[]
include::core-filters.adoc[] include::core-filters.adoc[]

View File

@ -276,14 +276,6 @@ Otherwise, you'll receive back an HTTP error code 403, which means "forbidden".
Spring Security has distinct classes responsible for most of the steps described above. Spring Security has distinct classes responsible for most of the steps described above.
The main participants (in the order that they are used) are the `ExceptionTranslationFilter`, an `AuthenticationEntryPoint` and an "authentication mechanism", which is responsible for calling the `AuthenticationManager` which we saw in the previous section. The main participants (in the order that they are used) are the `ExceptionTranslationFilter`, an `AuthenticationEntryPoint` and an "authentication mechanism", which is responsible for calling the `AuthenticationManager` which we saw in the previous section.
==== ExceptionTranslationFilter
`ExceptionTranslationFilter` is a Spring Security filter that has responsibility for detecting any Spring Security exceptions that are thrown.
Such exceptions will generally be thrown by an `AbstractSecurityInterceptor`, which is the main provider of authorization services.
We will discuss `AbstractSecurityInterceptor` in the next section, but for now we just need to know that it produces Java exceptions and knows nothing about HTTP or how to go about authenticating a principal.
Instead the `ExceptionTranslationFilter` offers this service, with specific responsibility for either returning error code 403 (if the principal has been authenticated and therefore simply lacks sufficient access - as per step seven above), or launching an `AuthenticationEntryPoint` (if the principal has not been authenticated and therefore we need to go commence step three).
[[tech-intro-auth-entry-point]] [[tech-intro-auth-entry-point]]
==== AuthenticationEntryPoint ==== AuthenticationEntryPoint
The `AuthenticationEntryPoint` is responsible for step three in the above list. The `AuthenticationEntryPoint` is responsible for step three in the above list.