SpringSecurity6从入门到实战之整合原生Filter链(源码级讲解,耐心看完!)

155 阅读5分钟

SpringSecurity6从入门到实战之整合原生Filter链

DelegatingFilterProxy

image.png

从官网上来进行学习可以看到第一个类就是DelegatingFilterProxy,我们首先看看官网给下的定义.

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

通过以上进行官网的翻译,我们知道了DelegatingFilterProxy是Servlet容器与Spring中bean容器的桥梁.我们在Spring框架中的Filter都是通过Bean注入的方式加载在容器中,在这可以得知DelegatingFilterProxy的作用就是实现把Serlet容器中的Filter和Spring容器中的Bean关联起来.所以当客户端请求进来先走过原生Filter之后就会到DelegatingFilterProxy进行关联.详细流程见下图.

image.png

下面可以看看相关源码

DelegatingFilterProxy

public class DelegatingFilterProxy extends GenericFilterBean {
​
    @Nullable
    private String contextAttribute;
​
    @Nullable
    private WebApplicationContext webApplicationContext;
​
    @Nullable
    private String targetBeanName;
​
    private boolean targetFilterLifecycle = false;
​
    @Nullable
    private volatile Filter delegate;
​
    private final Object delegateMonitor = new Object();
...
​
}

GenericFilterBean

public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
        EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {
​
    /** Logger available to subclasses. */
    protected final Log logger = LogFactory.getLog(getClass());
​
    @Nullable
    private String beanName;
​
    @Nullable
    private Environment environment;
​
    @Nullable
    private ServletContext servletContext;
​
    @Nullable
    private FilterConfig filterConfig;
​
    private final Set<String> requiredProperties = new HashSet<>(4);
        ...
        }

DelegatingFilterProxy 类继承于抽象类 GenericFilterBean 间接 implements 了 javax.servlet.Filter 接口。SpringSecurity中的Filter是Spring工厂中的Bean,无法直接处理客户端请求,需要通过DelegatingFilterProxy 来进行搭建桥梁.

FiterChainProxy

image.png

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

  • FilterChainProxy 类继承于抽象类 GenericFilterBean 间接 implements 了 javax.servlet.Filter 接口。
  • Servlet容器启动时自动调用
  • 作用:实现把 请求传递给一或多个 SecurityFilterChain 实例进行认证或授权等(根据客户端的请求去匹配是哪个SecurityFilterChain 中的过滤器),并在需要时重定向或返回错误信息。
  • 管理一或多个 SecurityFilterChain 过滤器链,这些过滤器链按顺序进行匹配,直到找到能处理当前请求的过滤器链为止。

image.png

SecurityFilterChain 接口

  • SecurityFilterChain 和 Servlet 中的 FilterChain 一样,同样维护了很多 Filter,这些 Filter 由 SpringSecurity 提供,每个 Filter 具有不同的职能。
  • Spring Security 支持添加1或多个 SecurityFilterChain,每个SecurityFilterChain负责不同的请求(比如依据请求地址进行区分),这样可以为不同的请求设置不同的认证规则。

image.png

小结:

  • Security Filter 并不是直接放在 Web 项目的原生 FilterChain 中,而是通过一个 FilterChainProxy 来统一管理
  • FilterChainProxy  是顶层管理者,统一管理 Security Filter 和 SecurityFIlterChain过滤器链
  • 当请求到达 FilterChainProxy 时,会根据当前请求匹配 SecurityFilterChain,然后将请求依次转发给 SecurityFilterChain 中的 Security Filter
  • FilterChainProxy 把 SecurityFilterChain 嵌入到 Web项目的原生过滤器链中
  • DelegatingFilterProxy 把 FilterChainProxy 整合到原生的过滤器链中

Security Filters

Spring Security 中最终对请求进行处理的就是某个 SecurityFilterChain 中的 Security Filter,这些Filter都设置为 Bean 注入到 Spring容器中,且会按照先后顺序执行。
​
下面展示 Spring Security 中给我们提供的过滤器,以及默认情况下会被加载的过滤器。
过滤器过滤器作用默认是否加载
DisableEncodeUrlFilter禁用 URL 重新编码YES
ForceEagerSessionCreationFilter管理是否强制生成新sessionNO
ChannelProcessingFilter过滤请求协议 HTTP 、HTTPSNO
WebAsyncManagerIntegrationFilter将 WebAsyncManger 与 SpringSecurity 上下文进行集成YES
SecurityContextHolderFilter获取安全上下文YES
SecurityContextPersistenceFilter处理请求之前,将安全信息加载到 SecurityContextHolder 中NO
HeaderWriterFilter处理头信息加入响应中YES
CorsFilter处理跨域问题NO
CsrfFilter处理 CSRF 攻击YES
LogoutFilter处理注销登录YES
OAuth2AuthorizationRequestRedirectFilter处理 OAuth2 认证重定向NO
Saml2WebSsoAuthenticationRequestFilter处理 SAML 认证NO
X509AuthenticationFilter处理 X509 认证NO
AbstractPreAuthenticatedProcessingFilter处理预认证问题NO
CasAuthenticationFilter处理 CAS 单点登录NO
OAuth2LoginAuthenticationFilter处理 OAuth2 认证NO
Saml2WebSsoAuthenticationFilter处理 SAML 认证NO
UsernamePasswordAuthenticationFilter处理表单登录YES
OpenIDAuthenticationFilter处理 OpenID 认证NO
DefaultLoginPageGeneratingFilter配置默认登录页面YES
DefaultLogoutPageGeneratingFilter配置默认注销页面YES
ConcurrentSessionFilter处理 Session 有效期NO
DigestAuthenticationFilter处理 HTTP 摘要认证NO
BearerTokenAuthenticationFilter处理 OAuth2 认证的 Access TokenNO
BasicAuthenticationFilter处理 HttpBasic 登录YES
RequestCacheAwareFilter处理请求缓存YES
SecurityContextHolderAwareRequestFilter包装原始请求YES
JaasApiIntegrationFilter处理 JAAS 认证NO
RememberMeAuthenticationFilter处理 RememberMe 登录NO
AnonymousAuthenticationFilter配置匿名认证YES
OAuth2AuthorizationCodeGrantFilter处理OAuth2认证中授权码NO
SessionManagementFilter处理 session 并发问题NO
ExceptionTranslationFilter处理认证/授权中的异常YES
FilterSecurityInterceptor对请求进行权限判断NO
AuthorizationFilter对请示进行访问权限处理YES
SwitchUserFilter处理账户切换NO

Spring Security 提供了 30 多个过滤器。默认情况下Spring Boot 在对 Spring Security 进行自动化配置时,会创建一个名为 SpringSecurityFilerChain 的过滤器,并注入到 Spring 容器中,这个过滤器将负责所有的安全管理,包括用户认证、授权、重定向到登录页面等.

这里我们通过源码来查看SpringBoot在自动化配置时是不是加载了以上的15个过滤器,SpringSecurityFilerChain是通过SpringSecurity的配置类进行加载的,那么我们进入WebSecurityConfiguration源码:

image.png

可以发现这个bean的名称就是springSecurityFilerChain,我们打上断点看看默认进行加载的过滤器有哪些

image.png

最终可以发现确实加载了这15个过滤器进来