1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Spring Security-部分官方文档翻译以及思考-SecurityFilterChain

Spring Security-部分官方文档翻译以及思考-SecurityFilterChain

时间:2020-11-12 23:30:26

相关推荐

Spring Security-部分官方文档翻译以及思考-SecurityFilterChain

回顾一下 Filter 过滤器

Spring Security的Servlet支持基于Servlet过滤器。

下图显示了单个HTTP请求处理程序的典型分层。

客户端向应用程序发送请求,容器创建一个FilterChain,其中包含 Filters 和Servlet,这些 Filters 和 Servlet 应根据请求URI的路径处理 HttpServletRequest。在Spring MVC应用程序中,Servlet 是 DispatcherServlet 的实例。最多一个 Servlet 可以处理单个 HttpServletRequest 和 HttpServletResponse 。但是,可以使用多个过滤器来:

防止调用下游 Filters 或 Servlet。在这种情况下,过滤器通常会写入 HttpServletResponse

修改下游 Filters 和 Servlet 使用的 HttpServletRequest 或 HttpServletResponse

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// do something before the rest of the applicationchain.doFilter(request, response); // invoke the rest of the application// do something after the rest of the application}

由于 Filters 只影响下游 Filters 和 Servlet ,因此每个 Filter 的调用顺序非常重要。

DelegatingFilterProxy

Spring提供了一个名为DelegatingFilterProxy的过滤器实现,它允许在 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间连接。 Servlet 容器允许使用自己的标准注册 Filters ,但它不知道 Spring bean 的定义。DelegatingFilterProxy可以通过标准的 Servlet 容器注册机制,将所有工作委托给实现过滤器的 Spring Bean 。

下面是DelegatingFilterProxy如何融入过滤器和过滤链的图片。

DelegatingFilterProxy从 ApplicationContext 中查找 Bean Filter0 ,然后调用 Bean Filter0 。

大白话就是:他的任务就是把持有的 bean 从容器中拿出来。

DelegatingFilterProxy的伪代码如下所示。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {// Lazily get Filter that was registered as a Spring Bean// For the example in DelegatingFilterProxydelegateis an instance of Bean Filter0Filter delegate = getFilterBean(someBeanName);// delegate work to the Spring Beandelegate.doFilter(request, response);}

DelegatingFilterProxy的另一个好处是,它允许延迟查找 Filter bean 实例。这一点很重要,因为容器需要在启动之前注册 Filter 实例。然而, Spring 通常使用ContextLoaderListener来加载 SpringBean ,直到需要注册 Filter 实例之后才能进行加载。

而注入到 servletContext 的方式是通过DelegatingFilterProxyRegistrationBean来完成,这个类的主要目的是为了包装DelegatingFilterProxy类,并且实现自动注入到 servletContext 的流程

DelegatingFilterProxy可以获取到FilterChainProxy这个bean,而这个 bean 注册SecurityFilterChain和其中的安全过滤器。

最后使用SecurityFilterChain来确定当前请求应该调用哪些Security Filter

所以DelegatingFilterProxyRegistrationBean就是为了将SecurityFilterChain加入servlet容器中。

DelegatingFilterProxy就是持有SecurityFilterChain的 bean 名称的一个 Filter 。

@Overridepublic DelegatingFilterProxy getFilter() {return new DelegatingFilterProxy(this.targetBeanName, getWebApplicationContext()) {@Overrideprotected void initFilterBean() throws ServletException {// Don't initialize filter bean on init()}};}

FilterChainProxy

Spring Security 的 Servlet 支持包含在FilterChainProxy中。FilterChainProxy是 Spring Security 提供的一种特殊 Filter ,允许通过SecurityFilterChain委托给许多 Filter 实例。由于FilterChainProxy是一个 Bean ,它通常被包装在DelegatingFilterProxy中。

也就是说DelegatingFilterProxy可以获取到FilterChainProxy这个bean

SecurityFilterChain

FilterChainProxy使用SecurityFilterChain来确定应该为此请求调用哪些 Spring 安全过滤器。

SecurityFilterChain中的 Security Filter 通常是 bean ,但它们是用FilterChainProxy注册的,而不是DelegatingFilterProxyFilterChainProxy提供了许多直接注册 Servlet 容器或DelegatingFilterProxy的优势。首先,它为 Spring Security 的所有 Servlet 支持提供了一个起点。因此,如果您试图解决 Spring Security 的 Servlet 支持问题,那么在FilterChainProxy中添加调试点是一个很好的开始。

DelegatingFilterProxy持有的是SecurityFilterChain这个 spring 容器中的 bean 名称。

FilterChainProxy持有的是一个拦截器链集合 List 。

其次,由于FilterChainProxy是 Spring Security 的核心,因此它可以执行不被视为可选的任务。例如,它可以清除 SecurityContext 以避免内存泄漏。它还可以应用 Spring Security 的 HttpFirewall 来保护应用程序免受某些类型的攻击。

此外,它在确定何时调用SecurityFilterChain方面提供了更大的灵活性。在 Servlet 容器中,仅基于URL调用 Filter 。然而,FilterChainProxy可以通过利用 RequestMatcher 接口根据 HttpServletRequest 中的任何内容确定调用。

事实上,FilterChainProxy可以用来确定应该使用哪个SecurityFilterChain。这允许为应用程序的不同部分提供完全独立的配置。

在多个SecurityFilterChain的图中,FilterChainProxy决定应使用哪个SecurityFilterChain。将仅调用匹配的第一个SecurityFilterChain。如果请求 /api/messages/ 的URL,它将首先匹配SecurityFilterChain0的 /api/** 模式,因此仅调用SecurityFilterChain0,即使它也匹配SecurityFilterChainn。如果请求了 /messages/ 的URL,它将与SecurityFilterChain0的 /api/** 模式不匹配,因此FilterChainProxy将继续尝试每个SecurityFilterChain。假设没有其他与SecurityFilterChain匹配的SecurityFilterChainn实例将被调用。

注意,SecurityFilterChain0只配置了三个安全过滤器实例。然而,SecurityFilterChainn配置了四个安全过滤器。需要注意的是,每个SecurityFilterChain都可以是唯一的,并且可以单独配置。事实上,如果应用程序希望 Spring security 忽略某些请求,则SecurityFilterChain可能没有安全过滤器。

FilterChainProxy创建Spring Security Filter Chain的过程

webSecurity.build()

@Configuration(proxyBeanMethods = false)public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {// .../*** Creates the Spring Security Filter Chain* @return the {@link Filter} that represents the security filter chain* @throws Exception*/@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)public Filter springSecurityFilterChain() throws Exception {boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();boolean hasFilterChain = !this.securityFilterChains.isEmpty();Assert.state(!(hasConfigurers && hasFilterChain),"Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");if (!hasConfigurers && !hasFilterChain) {WebSecurityConfigurerAdapter adapter = this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {});this.webSecurity.apply(adapter);}for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);for (Filter filter : securityFilterChain.getFilters()) {if (filter instanceof FilterSecurityInterceptor) {this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);break;}}}for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {customizer.customize(this.webSecurity);}return this.webSecurity.build();}// ...}

doBuild()

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {// ...@Overridepublic final O build() throws Exception {if (pareAndSet(false, true)) {this.object = doBuild();return this.object;}throw new AlreadyBuiltException("This object has already been built");}// ...}

performBuild()

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>extends AbstractSecurityBuilder<O> {// ...@Overrideprotected final O doBuild() throws Exception {synchronized (this.configurers) {this.buildState = BuildState.INITIALIZING;beforeInit();init();this.buildState = BuildState.CONFIGURING;beforeConfigure();configure();this.buildState = BuildState.BUILDING;O result = performBuild();this.buildState = BuildState.BUILT;return result;}}// ...}

创建 FilterChainProxy

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。