转载

Spring Security 整体结构概览

Spring Security的功能可以概括为两部分,即认证和授权。

认证就是一个用户使用令牌(最常见的是账号和密码)登陆,服务器验证这个用户的令牌是否有效。

授权则是认证之后,系统根据这个用户的信息判断他拥有哪些权限,能访问哪种资源,能对资源进何种操作,并向他授予相关的权限,对没有权限访问的用户进行阻止。

这里说的Spring Security是基于Servlet容器的。

从Filter说起

Spring Security的Servlet支持是基于Servlet的 Filter 的。Filter可以对请求进行处理,但Filter一般会将处理好的请求交给 FilterChain 中的下一个Filter,即一个个Filter按照相应的顺序组合起来形成了一个Filter链,从而达到对请求进行过滤/提前处理的效果。

Spring Security 整体结构概览

当请求到达时,Servlet容器会初始化一个 FilterChain ,并将请求传递到里面进行处理:

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

经过一个个Filter处理后请求才到达Servlet处理并响应,由此可见,Filter在 FilterChain 中组织的顺序非常重要。

DelegatingFilterProxy

因为Servlet容器跟Spring的IoC容器是两种不同的容器,Servlet容器无法获知Spring容器中各种Bean(用户自定义Filter)的信息,也无法直接使用这些Bean(Filter),所以需要在两者间建立桥梁,使得我们定义的Bean(Filter)能够被Servlet容器使用。

Spring提供了一种叫 DelegatingFilterProxy 的Filter实现。

Spring Security 整体结构概览

它像普通的Filter一样被插入到 FilterChain 中,它的功能是将请求委托给Spring容器里的Bean Filter来处理,从而建立起Servlet容器和Spring容器之间的桥梁。

例如图中 DelegatingFilterProxy 会在Spring容器中寻找 Bean Filter0 ,并将 ServletRequestServletResponse 传递过去:

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

DelegatingFilterProxy 的另一个好处是它可以延迟加载Bean Filter实例,因为 FilterChain 会在Servlet容器启动前初始化,这样可以提升Servlet容器启动的性能。

FilterChainProxy

上面提到 DelegatingFilterProxy 会将请求委托给Bean Filter,而其实这里的Bean Filter也不会直接处理请求,会将请求进一步转发,这个Bean Filter即是 FilterChainProxy

FilterChainProxy 是Spring Security提供的特殊Filter,它会将请求委托到另一种 FilterChain 中,即Spring的FilterChain: SecurityFilterChain

Spring Security 整体结构概览

我们可以很自然地想到, SecurityFilterChain 中便是Spring的Bean Filter了,即 SecurityFilter

Spring Security 整体结构概览

这里的 SecurityFilter 就是普通的Bean,他们可以识别自己能处理的请求并对请求处理,否则将请求传给链中的下一个Filter,例如最常见的 UsernamePasswordAuthenticationFilter 可以识别处理基于表单的登陆请求。

值得注意的是, SecurityFilterChain 可以有多条,可以根据不同的请求来判断请求应该被传递到哪个 SecurityFilterChain 中:

比如符合 /api/** 匹配模式的URL应该被传递到最上面的 SecurityFilterChain 中,这个请求一旦匹配到了某个上游的 SecurityFilterChain ,下游的 SecurityFilterChain 就不会再进行匹配。

Spring Security 整体结构概览

有哪些Security Filter?

官方文档给出了按照Spring Security Filter排列顺序的列表:

Security Filters

处理安全异常

ExceptionTranslationFilter 允许将 AccessDeniedExceptionAuthenticationException 异常转换为HTTP响应,从它的名字可以看到,它也是一个Filter,可以被插入到 SecurityFilterChain 中,这是它的工作流程:

Spring Security 整体结构概览
  1. 它调用下层的Filter处理请求
  2. 如果下层Filter抛出 AuthenticationException ,则会被它捕获(见下面代码),并调用它的 startAuthentication() 方法跳转进行认证。(图中的 SecurityContextHolder 等几个东西属于认证功能部分,可以先不用管)
  3. 如果下层Filter抛出 AccessDeniedException 则对异常作出响应,通知用户禁止访问。
原文  https://juejin.im/post/5f13c3096fb9a07e8c68b407
正文到此结束
Loading...