(window.webpackJsonp=window.webpackJsonp||[]).push([[227],{653:function(e,t,i){"use strict";i.r(t);var r=i(56),n=Object(r.a)({},(function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[i("h1",{attrs:{id:"architecture"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#architecture"}},[e._v("#")]),e._v(" Architecture")]),e._v(" "),i("p",[e._v("This section discusses Spring Security’s high level architecture within Servlet based applications.\nWe build on this high level understanding within "),i("RouterLink",{attrs:{to:"/en/spring-security/authentication/index.html#servlet-authentication"}},[e._v("Authentication")]),e._v(", "),i("RouterLink",{attrs:{to:"/en/spring-security/authorization/index.html#servlet-authorization"}},[e._v("Authorization")]),e._v(", "),i("RouterLink",{attrs:{to:"/en/spring-security/exploits/index.html#servlet-exploits"}},[e._v("Protection Against Exploits")]),e._v(" sections of the reference.")],1),e._v(" "),i("h2",{attrs:{id:"a-review-of-filters"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#a-review-of-filters"}},[e._v("#")]),e._v(" A Review of "),i("code",[e._v("Filter")]),e._v("s")]),e._v(" "),i("p",[e._v("Spring Security’s Servlet support is based on Servlet "),i("code",[e._v("Filter")]),e._v("s, so it is helpful to look at the role of "),i("code",[e._v("Filter")]),e._v("s generally first.\nThe picture below shows the typical layering of the handlers for a single HTTP request.")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/filterchain.png",alt:"filterchain"}})]),e._v(" "),i("p",[e._v("Figure 1. FilterChain")]),e._v(" "),i("p",[e._v("The client sends a request to the application, and the container creates a "),i("code",[e._v("FilterChain")]),e._v(" which contains the "),i("code",[e._v("Filter")]),e._v("s and "),i("code",[e._v("Servlet")]),e._v(" that should process the "),i("code",[e._v("HttpServletRequest")]),e._v(" based on the path of the request URI.\nIn a Spring MVC application the "),i("code",[e._v("Servlet")]),e._v(" is an instance of "),i("a",{attrs:{href:"https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/web.html#mvc-servlet",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("DispatcherServlet")]),i("OutboundLink")],1),e._v(".\nAt most one "),i("code",[e._v("Servlet")]),e._v(" can handle a single "),i("code",[e._v("HttpServletRequest")]),e._v(" and "),i("code",[e._v("HttpServletResponse")]),e._v(".\nHowever, more than one "),i("code",[e._v("Filter")]),e._v(" can be used to:")]),e._v(" "),i("ul",[i("li",[i("p",[e._v("Prevent downstream "),i("code",[e._v("Filter")]),e._v("s or the "),i("code",[e._v("Servlet")]),e._v(" from being invoked.\nIn this instance the "),i("code",[e._v("Filter")]),e._v(" will typically write the "),i("code",[e._v("HttpServletResponse")]),e._v(".")])]),e._v(" "),i("li",[i("p",[e._v("Modify the "),i("code",[e._v("HttpServletRequest")]),e._v(" or "),i("code",[e._v("HttpServletResponse")]),e._v(" used by the downstream "),i("code",[e._v("Filter")]),e._v("s and "),i("code",[e._v("Servlet")])])])]),e._v(" "),i("p",[e._v("The power of the "),i("code",[e._v("Filter")]),e._v(" comes from the "),i("code",[e._v("FilterChain")]),e._v(" that is passed into it.")]),e._v(" "),i("p",[e._v("Example 1. "),i("code",[e._v("FilterChain")]),e._v(" Usage Example")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {\n\t// do something before the rest of the application\n chain.doFilter(request, response); // invoke the rest of the application\n // do something after the rest of the application\n}\n")])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {\n // do something before the rest of the application\n chain.doFilter(request, response) // invoke the rest of the application\n // do something after the rest of the application\n}\n")])])]),i("p",[e._v("Since a "),i("code",[e._v("Filter")]),e._v(" only impacts downstream "),i("code",[e._v("Filter")]),e._v("s and the "),i("code",[e._v("Servlet")]),e._v(", the order each "),i("code",[e._v("Filter")]),e._v(" is invoked is extremely important.")]),e._v(" "),i("h2",{attrs:{id:"delegatingfilterproxy"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#delegatingfilterproxy"}},[e._v("#")]),e._v(" DelegatingFilterProxy")]),e._v(" "),i("p",[e._v("Spring provides a "),i("code",[e._v("Filter")]),e._v(" implementation named "),i("a",{attrs:{href:"https://docs.spring.io/spring-framework/docs/5.3.16/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("DelegatingFilterProxy")]),i("OutboundLink")],1),e._v(" that allows bridging between the Servlet container’s lifecycle and Spring’s "),i("code",[e._v("ApplicationContext")]),e._v(".\nThe Servlet container allows registering "),i("code",[e._v("Filter")]),e._v("s using its own standards, but it is not aware of Spring defined Beans."),i("code",[e._v("DelegatingFilterProxy")]),e._v(" can be registered via standard Servlet container mechanisms, but delegate all the work to a Spring Bean that implements "),i("code",[e._v("Filter")]),e._v(".")]),e._v(" "),i("p",[e._v("Here is a picture of how "),i("code",[e._v("DelegatingFilterProxy")]),e._v(" fits into the "),i("a",{attrs:{href:"#servlet-filters-review"}},[i("code",[e._v("Filter")]),e._v("s and the "),i("code",[e._v("FilterChain")])]),e._v(".")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/delegatingfilterproxy.png",alt:"delegatingfilterproxy"}})]),e._v(" "),i("p",[e._v("Figure 2. DelegatingFilterProxy")]),e._v(" "),i("p",[i("code",[e._v("DelegatingFilterProxy")]),e._v(" looks up "),i("em",[e._v("Bean Filter"),i("sub",[e._v("0")])]),e._v(" from the "),i("code",[e._v("ApplicationContext")]),e._v(" and then invokes "),i("em",[e._v("Bean Filter"),i("sub",[e._v("0")])]),e._v(".\nThe pseudo code of "),i("code",[e._v("DelegatingFilterProxy")]),e._v(" can be seen below.")]),e._v(" "),i("p",[e._v("Example 2. "),i("code",[e._v("DelegatingFilterProxy")]),e._v(" Pseudo Code")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {\n\t// Lazily get Filter that was registered as a Spring Bean\n\t// For the example in DelegatingFilterProxy delegate is an instance of Bean Filter0\n\tFilter delegate = getFilterBean(someBeanName);\n\t// delegate work to the Spring Bean\n\tdelegate.doFilter(request, response);\n}\n")])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {\n\t// Lazily get Filter that was registered as a Spring Bean\n\t// For the example in DelegatingFilterProxy delegate is an instance of Bean Filter0\n\tval delegate: Filter = getFilterBean(someBeanName)\n\t// delegate work to the Spring Bean\n\tdelegate.doFilter(request, response)\n}\n")])])]),i("p",[e._v("Another benefit of "),i("code",[e._v("DelegatingFilterProxy")]),e._v(" is that it allows delaying looking "),i("code",[e._v("Filter")]),e._v(" bean instances.\nThis is important because the container needs to register the "),i("code",[e._v("Filter")]),e._v(" instances before the container can startup.\nHowever, Spring typically uses a "),i("code",[e._v("ContextLoaderListener")]),e._v(" to load the Spring Beans which will not be done until after the "),i("code",[e._v("Filter")]),e._v(" instances need to be registered.")]),e._v(" "),i("h2",{attrs:{id:"filterchainproxy"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#filterchainproxy"}},[e._v("#")]),e._v(" FilterChainProxy")]),e._v(" "),i("p",[e._v("Spring Security’s Servlet support is contained within "),i("code",[e._v("FilterChainProxy")]),e._v("."),i("code",[e._v("FilterChainProxy")]),e._v(" is a special "),i("code",[e._v("Filter")]),e._v(" provided by Spring Security that allows delegating to many "),i("code",[e._v("Filter")]),e._v(" instances through "),i("a",{attrs:{href:"#servlet-securityfilterchain"}},[i("code",[e._v("SecurityFilterChain")])]),e._v(".\nSince "),i("code",[e._v("FilterChainProxy")]),e._v(" is a Bean, it is typically wrapped in a "),i("a",{attrs:{href:"#servlet-delegatingfilterproxy"}},[e._v("DelegatingFilterProxy")]),e._v(".")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/filterchainproxy.png",alt:"filterchainproxy"}})]),e._v(" "),i("p",[e._v("Figure 3. FilterChainProxy")]),e._v(" "),i("h2",{attrs:{id:"securityfilterchain"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#securityfilterchain"}},[e._v("#")]),e._v(" SecurityFilterChain")]),e._v(" "),i("p",[i("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/5.6.2/api/org/springframework/security/web/SecurityFilterChain.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("SecurityFilterChain")]),i("OutboundLink")],1),e._v(" is used by "),i("a",{attrs:{href:"#servlet-filterchainproxy"}},[e._v("FilterChainProxy")]),e._v(" to determine which Spring Security "),i("code",[e._v("Filter")]),e._v("s should be invoked for this request.")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/securityfilterchain.png",alt:"securityfilterchain"}})]),e._v(" "),i("p",[e._v("Figure 4. SecurityFilterChain")]),e._v(" "),i("p",[e._v("The "),i("a",{attrs:{href:"#servlet-security-filters"}},[e._v("Security Filters")]),e._v(" in "),i("code",[e._v("SecurityFilterChain")]),e._v(" are typically Beans, but they are registered with "),i("code",[e._v("FilterChainProxy")]),e._v(" instead of "),i("a",{attrs:{href:"#servlet-delegatingfilterproxy"}},[e._v("DelegatingFilterProxy")]),e._v("."),i("code",[e._v("FilterChainProxy")]),e._v(" provides a number of advantages to registering directly with the Servlet container or "),i("a",{attrs:{href:"#servlet-delegatingfilterproxy"}},[e._v("DelegatingFilterProxy")]),e._v(".\nFirst, it provides a starting point for all of Spring Security’s Servlet support.\nFor that reason, if you are attempting to troubleshoot Spring Security’s Servlet support, adding a debug point in "),i("code",[e._v("FilterChainProxy")]),e._v(" is a great place to start.")]),e._v(" "),i("p",[e._v("Second, since "),i("code",[e._v("FilterChainProxy")]),e._v(" is central to Spring Security usage it can perform tasks that are not viewed as optional.\nFor example, it clears out the "),i("code",[e._v("SecurityContext")]),e._v(" to avoid memory leaks.\nIt also applies Spring Security’s "),i("RouterLink",{attrs:{to:"/en/spring-security/exploits/firewall.html#servlet-httpfirewall"}},[i("code",[e._v("HttpFirewall")])]),e._v(" to protect applications against certain types of attacks.")],1),e._v(" "),i("p",[e._v("In addition, it provides more flexibility in determining when a "),i("code",[e._v("SecurityFilterChain")]),e._v(" should be invoked.\nIn a Servlet container, "),i("code",[e._v("Filter")]),e._v("s are invoked based upon the URL alone.\nHowever, "),i("code",[e._v("FilterChainProxy")]),e._v(" can determine invocation based upon anything in the "),i("code",[e._v("HttpServletRequest")]),e._v(" by leveraging the "),i("code",[e._v("RequestMatcher")]),e._v(" interface.")]),e._v(" "),i("p",[e._v("In fact, "),i("code",[e._v("FilterChainProxy")]),e._v(" can be used to determine which "),i("code",[e._v("SecurityFilterChain")]),e._v(" should be used.\nThis allows providing a totally separate configuration for different "),i("em",[e._v("slices")]),e._v(" of your application.")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/multi-securityfilterchain.png",alt:"multi securityfilterchain"}})]),e._v(" "),i("p",[e._v("Figure 5. Multiple SecurityFilterChain")]),e._v(" "),i("p",[e._v("In the "),i("a",{attrs:{href:"#servlet-multi-securityfilterchain-figure"}},[e._v("Multiple SecurityFilterChain")]),e._v(" Figure "),i("code",[e._v("FilterChainProxy")]),e._v(" decides which "),i("code",[e._v("SecurityFilterChain")]),e._v(" should be used.\nOnly the first "),i("code",[e._v("SecurityFilterChain")]),e._v(" that matches will be invoked.\nIf a URL of "),i("code",[e._v("/api/messages/")]),e._v(" is requested, it will first match on "),i("code",[e._v("SecurityFilterChain0")]),e._v("'s pattern of "),i("code",[e._v("/api/**")]),e._v(", so only "),i("code",[e._v("SecurityFilterChain0")]),e._v(" will be invoked even though it also matches on "),i("code",[e._v("SecurityFilterChainn")]),e._v(".\nIf a URL of "),i("code",[e._v("/messages/")]),e._v(" is requested, it will not match on "),i("code",[e._v("SecurityFilterChain0")]),e._v("'s pattern of "),i("code",[e._v("/api/**")]),e._v(", so "),i("code",[e._v("FilterChainProxy")]),e._v(" will continue trying each "),i("code",[e._v("SecurityFilterChain")]),e._v(".\nAssuming that no other, "),i("code",[e._v("SecurityFilterChain")]),e._v(" instances match "),i("code",[e._v("SecurityFilterChainn")]),e._v(" will be invoked.")]),e._v(" "),i("p",[e._v("Notice that "),i("code",[e._v("SecurityFilterChain0")]),e._v(" has only three security "),i("code",[e._v("Filter")]),e._v("s instances configured.\nHowever, "),i("code",[e._v("SecurityFilterChainn")]),e._v(" has four security "),i("code",[e._v("Filter")]),e._v("s configured.\nIt is important to note that each "),i("code",[e._v("SecurityFilterChain")]),e._v(" can be unique and configured in isolation.\nIn fact, a "),i("code",[e._v("SecurityFilterChain")]),e._v(" might have zero security "),i("code",[e._v("Filter")]),e._v("s if the application wants Spring Security to ignore certain requests.")]),e._v(" "),i("h2",{attrs:{id:"security-filters"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#security-filters"}},[e._v("#")]),e._v(" Security Filters")]),e._v(" "),i("p",[e._v("The Security Filters are inserted into the "),i("a",{attrs:{href:"#servlet-filterchainproxy"}},[e._v("FilterChainProxy")]),e._v(" with the "),i("a",{attrs:{href:"#servlet-securityfilterchain"}},[e._v("SecurityFilterChain")]),e._v(" API.\nThe "),i("a",{attrs:{href:"#servlet-filters-review"}},[e._v("order of "),i("code",[e._v("Filter")])]),e._v("s matters.\nIt is typically not necessary to know the ordering of Spring Security’s "),i("code",[e._v("Filter")]),e._v("s.\nHowever, there are times that it is beneficial to know the ordering")]),e._v(" "),i("p",[e._v("Below is a comprehensive list of Spring Security Filter ordering:")]),e._v(" "),i("ul",[i("li",[i("p",[e._v("ChannelProcessingFilter")])]),e._v(" "),i("li",[i("p",[e._v("WebAsyncManagerIntegrationFilter")])]),e._v(" "),i("li",[i("p",[e._v("SecurityContextPersistenceFilter")])]),e._v(" "),i("li",[i("p",[e._v("HeaderWriterFilter")])]),e._v(" "),i("li",[i("p",[e._v("CorsFilter")])]),e._v(" "),i("li",[i("p",[e._v("CsrfFilter")])]),e._v(" "),i("li",[i("p",[e._v("LogoutFilter")])]),e._v(" "),i("li",[i("p",[e._v("OAuth2AuthorizationRequestRedirectFilter")])]),e._v(" "),i("li",[i("p",[e._v("Saml2WebSsoAuthenticationRequestFilter")])]),e._v(" "),i("li",[i("p",[e._v("X509AuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("AbstractPreAuthenticatedProcessingFilter")])]),e._v(" "),i("li",[i("p",[e._v("CasAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("OAuth2LoginAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("Saml2WebSsoAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/authentication/passwords/form.html#servlet-authentication-usernamepasswordauthenticationfilter"}},[i("code",[e._v("UsernamePasswordAuthenticationFilter")])])],1)]),e._v(" "),i("li",[i("p",[e._v("OpenIDAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("DefaultLoginPageGeneratingFilter")])]),e._v(" "),i("li",[i("p",[e._v("DefaultLogoutPageGeneratingFilter")])]),e._v(" "),i("li",[i("p",[e._v("ConcurrentSessionFilter")])]),e._v(" "),i("li",[i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/authentication/passwords/digest.html#servlet-authentication-digest"}},[i("code",[e._v("DigestAuthenticationFilter")])])],1)]),e._v(" "),i("li",[i("p",[e._v("BearerTokenAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/authentication/passwords/basic.html#servlet-authentication-basic"}},[i("code",[e._v("BasicAuthenticationFilter")])])],1)]),e._v(" "),i("li",[i("p",[e._v("RequestCacheAwareFilter")])]),e._v(" "),i("li",[i("p",[e._v("SecurityContextHolderAwareRequestFilter")])]),e._v(" "),i("li",[i("p",[e._v("JaasApiIntegrationFilter")])]),e._v(" "),i("li",[i("p",[e._v("RememberMeAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("AnonymousAuthenticationFilter")])]),e._v(" "),i("li",[i("p",[e._v("OAuth2AuthorizationCodeGrantFilter")])]),e._v(" "),i("li",[i("p",[e._v("SessionManagementFilter")])]),e._v(" "),i("li",[i("p",[i("a",{attrs:{href:"#servlet-exceptiontranslationfilter"}},[i("code",[e._v("ExceptionTranslationFilter")])])])]),e._v(" "),i("li",[i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/authorization/authorize-requests.html#servlet-authorization-filtersecurityinterceptor"}},[i("code",[e._v("FilterSecurityInterceptor")])])],1)]),e._v(" "),i("li",[i("p",[e._v("SwitchUserFilter")])])]),e._v(" "),i("h2",{attrs:{id:"handling-security-exceptions"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#handling-security-exceptions"}},[e._v("#")]),e._v(" Handling Security Exceptions")]),e._v(" "),i("p",[e._v("The "),i("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/5.6.2/api/org/springframework/security/web/access/ExceptionTranslationFilter.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("ExceptionTranslationFilter")]),i("OutboundLink")],1),e._v(" allows translation of "),i("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/5.6.2/api/org/springframework/security/access/AccessDeniedException.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("AccessDeniedException")]),i("OutboundLink")],1),e._v(" and "),i("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/5.6.2/api//org/springframework/security/core/AuthenticationException.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("AuthenticationException")]),i("OutboundLink")],1),e._v(" into HTTP responses.")]),e._v(" "),i("p",[i("code",[e._v("ExceptionTranslationFilter")]),e._v(" is inserted into the "),i("a",{attrs:{href:"#servlet-filterchainproxy"}},[e._v("FilterChainProxy")]),e._v(" as one of the "),i("a",{attrs:{href:"#servlet-security-filters"}},[e._v("Security Filters")]),e._v(".")]),e._v(" "),i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/servlet/architecture/exceptiontranslationfilter.png",alt:"exceptiontranslationfilter"}})]),e._v(" "),i("ul",[i("li",[i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/icons/number_1.png",alt:"number 1"}}),e._v(" First, the "),i("code",[e._v("ExceptionTranslationFilter")]),e._v(" invokes "),i("code",[e._v("FilterChain.doFilter(request, response)")]),e._v(" to invoke the rest of the application.")])]),e._v(" "),i("li",[i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/icons/number_2.png",alt:"number 2"}}),e._v(" If the user is not authenticated or it is an "),i("code",[e._v("AuthenticationException")]),e._v(", then "),i("em",[e._v("Start Authentication")]),e._v(".")]),e._v(" "),i("ul",[i("li",[i("p",[e._v("The "),i("RouterLink",{attrs:{to:"/en/spring-security/authentication/architecture.html#servlet-authentication-securitycontextholder"}},[e._v("SecurityContextHolder")]),e._v(" is cleared out")],1)]),e._v(" "),i("li",[i("p",[e._v("The "),i("code",[e._v("HttpServletRequest")]),e._v(" is saved in the "),i("a",{attrs:{href:"https://docs.spring.io/spring-security/site/docs/5.6.2/api/org/springframework/security/web/savedrequest/RequestCache.html",target:"_blank",rel:"noopener noreferrer"}},[i("code",[e._v("RequestCache")]),i("OutboundLink")],1),e._v(".\nWhen the user successfully authenticates, the "),i("code",[e._v("RequestCache")]),e._v(" is used to replay the original request.")])]),e._v(" "),i("li",[i("p",[e._v("The "),i("code",[e._v("AuthenticationEntryPoint")]),e._v(" is used to request credentials from the client.\nFor example, it might redirect to a log in page or send a "),i("code",[e._v("WWW-Authenticate")]),e._v(" header.")])])])]),e._v(" "),i("li",[i("p",[i("img",{attrs:{src:"https://docs.spring.io/spring-security/reference/_images/icons/number_3.png",alt:"number 3"}}),e._v(" Otherwise if it is an "),i("code",[e._v("AccessDeniedException")]),e._v(", then "),i("em",[e._v("Access Denied")]),e._v(".\nThe "),i("code",[e._v("AccessDeniedHandler")]),e._v(" is invoked to handle access denied.")])])]),e._v(" "),i("table",[i("thead",[i("tr",[i("th"),e._v(" "),i("th",[e._v("If the application does not throw an "),i("code",[e._v("AccessDeniedException")]),e._v(" or an "),i("code",[e._v("AuthenticationException")]),e._v(", then "),i("code",[e._v("ExceptionTranslationFilter")]),e._v(" does not do anything.")])])]),e._v(" "),i("tbody")]),e._v(" "),i("p",[e._v("The pseudocode for "),i("code",[e._v("ExceptionTranslationFilter")]),e._v(" looks something like this:")]),e._v(" "),i("p",[e._v("ExceptionTranslationFilter pseudocode")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("try {\n\tfilterChain.doFilter(request, response); (1)\n} catch (AccessDeniedException | AuthenticationException ex) {\n\tif (!authenticated || ex instanceof AuthenticationException) {\n\t\tstartAuthentication(); (2)\n\t} else {\n\t\taccessDenied(); (3)\n\t}\n}\n")])])]),i("table",[i("thead",[i("tr",[i("th",[i("strong",[e._v("1")])]),e._v(" "),i("th",[e._v("You will recall from "),i("a",{attrs:{href:"#servlet-filters-review"}},[e._v("A Review of "),i("code",[e._v("Filter")]),e._v("s")]),e._v(" that invoking "),i("code",[e._v("FilterChain.doFilter(request, response)")]),e._v(" is the equivalent of invoking the rest of the application."),i("br"),e._v("This means that if another part of the application, (i.e. "),i("RouterLink",{attrs:{to:"/en/spring-security/authorization/authorize-requests.html#servlet-authorization-filtersecurityinterceptor"}},[i("code",[e._v("FilterSecurityInterceptor")])]),e._v(" or method security) throws an "),i("code",[e._v("AuthenticationException")]),e._v(" or "),i("code",[e._v("AccessDeniedException")]),e._v(" it will be caught and handled here.")],1)])]),e._v(" "),i("tbody",[i("tr",[i("td",[i("strong",[e._v("2")])]),e._v(" "),i("td",[e._v("If the user is not authenticated or it is an "),i("code",[e._v("AuthenticationException")]),e._v(", then "),i("em",[e._v("Start Authentication")]),e._v(".")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("3")])]),e._v(" "),i("td",[e._v("Otherwise, "),i("em",[e._v("Access Denied")])])])])]),e._v(" "),i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/getting-started.html"}},[e._v("Getting Started")]),i("RouterLink",{attrs:{to:"/en/spring-security/authentication/index.html"}},[e._v("Authentication")])],1)])}),[],!1,null,null,null);t.default=n.exports}}]);