在web应用开发中,安全无疑是十分重要的,选择Spring Security来保护web应用是一个非常好的选择。Spring Security 是spring项目之中的一个安全模块,可以非常方便与spring项目无缝集成。
简介
Spring Security 的核心主要是一系列的过滤器链。
Spring Security 在 Servlet 的过滤链(filter chain)中注册了一个过滤器 FilterChainProxy,它会把请求代理到 Spring Security 自己维护的多个过滤链,每个过滤链会匹配一些 URL,如果匹配则执行对应的过滤器。过滤链是有顺序的,一个请求只会执行第一条匹配的过滤链。Spring Security 的配置本质上就是新增、删除、修改过滤器。
Spring Security的过滤链
本质上是一连串的Filter, 然后又以一个独立的Filter的形式插入到Filter Chain里,其名为FilterChainProxy。
实际上FilterChainProxy下面可以有多条Filter Chain,来针对不同的URL做验证,而Filter Chain中所拥有的Filter则会根据定义的服务自动增减。所以无需要显示再定义这些Filter,除非想要实现自己的逻辑。
绿色部分:
代表过滤器,每个方块都代表一个过滤器。- UsernamePasswordAuthenticationFilter用来处理表单登录的。检查当前的请求是不是一个登录请求,然后再这个请求里面带没带用户名和密码,如果带了用户名和密码,这个过滤器就会用用户名和密码尝试去登录,如果这个请求里面没有带用户名和密码,继续进行下面的过滤器。
- BasicAuthenticationFilter用来处理HTTPBasic登录的。检查请求的请求头中是不是有Basic开头的authentication的信息,如果有的话,会尝试拿出来做basic流的字节码然后从中取出用户名和密码尝试做登录。
springsecurity还提供了许多其他的认证方式,任何一个过滤器,成功的完成用户登录以后,都会再这个请求上做个标记,表明这个用户已经认证成功了。
蓝色部分:
在Exception Translation Filter中,捕获橙色部分FilterSecurity Interceptor抛出的异常,会根据抛出的异常,会做相应的处理。橙色部分:
请求经历过这些过滤器后,就会到达这个写橘黄色的拦截器上比如FilterSecurity Interceptor,这个拦截器是整个Spring Security过滤器的最后一环,是最终的守门人,在它身后是我们自己写的controller的rest服务,在该拦截器中,它会去决定当前的请求能不能去访问后面真正的服务。如果验证不通过,则会往前抛出异常。
绿色的部分可以通过配置来设置是否生效,除了绿色之外的过滤器,是不能通过配置来控制的,而且位置也不能更改,不能移除到过滤器链外的。
在FilterSecurityInterceptor中,
- 我们可以看到所有的判断逻辑是在beforeInvocation中执行的。
- 当判断逻辑通过后,执行doFilter,是真正开始调用controller中的restful服务了。
在ExceptionTranslationFilter中,主要是用来处理异常的,
- 其中doFilter方法比较简单,主要是调用后面过滤器中的doFilter方法。
- 主要逻辑主要是在catch中,捕获到异常以后如何处理。
在UsernamePasswordAuthenticationFilter中,主要完成了对登录的验证,
- 只处理POST类型的/login的请求
- 收到请求后,从Request中拿到用户名与密码,然后进行登录。
两种认证方式
HTTP Basic
1 | // BrowserSecurityConfig.java |
Form表单
1 | // BrowserSecurityConfig.java |
过滤器链中常用的过滤器
SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。现在对这条过滤器链的各个进行说明:
- WebAsyncManagerIntegrationFilter:将 Security 上下文与 Spring Web 中用于处理异步请求映射的 WebAsyncManager 进行集成。
- SecurityContextPersistenceFilter:在每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中,然后在该次请求处理完成之后,将 SecurityContextHolder 中关于这次请求的信息存储到一个“仓储”中,然后将 SecurityContextHolder 中的信息清除,例如在Session中维护一个用户的安全信息就是这个过滤器处理的。
- HeaderWriterFilter:用于将头信息加入响应中。
- CsrfFilter:用于处理跨站请求伪造。
- LogoutFilter:用于处理退出登录。
- UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。默认情况下处理来自 /login 的请求。从表单中获取用户名和密码时,默认使用的表单 name 值为 username 和 password,这两个值可以通过设置这个过滤器的usernameParameter 和 passwordParameter 两个参数的值进行修改。
- DefaultLoginPageGeneratingFilter:如果没有配置登录页面,那系统初始化时就会配置这个过滤器,并且用于在需要进行登录时生成一个登录表单页面。
- DefaultLogoutPageGeneratingFilter:如果没有配置登出页面,那系统初始化时就会配置这个过滤器。
- BasicAuthenticationFilter:检测和处理 http basic 认证。
- RequestCacheAwareFilter:用来处理请求的缓存。
- SecurityContextHolderAwareRequestFilter:主要是包装请求对象request。
- RememberMeAuthenticationFilter:当用户没有登录而直接访问资源时, 从 cookie 里找出用户的信息, 如果 Spring Security 能够识别出用户提供的remember me cookie, 用户将不必填写用户名和密码, 而是直接登录进入系统,该过滤器默认不开启。
- AnonymousAuthenticationFilter:检测 SecurityContextHolder 中是否存在 Authentication 对象,如果不存在为其提供一个匿名 Authentication。
- SessionManagementFilter:管理 session 的过滤器
- ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常。
- FilterSecurityInterceptor:可以看做过滤器链的出口。