面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • spring全家桶

    • IOC
    • AOP
    • spring MVC
    • springSecurity
      • 面试问题
      • 循环依赖
      • 事务
      • 启动流程和配置
      • 注解相关
    • mybatis

    • 中间件

    • 框架
    • spring全家桶
    小游
    2021-03-23

    springSecurity

    SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。现在对这条过滤器链的各个进行说明:

    1. WebAsyncManagerIntegrationFilter:将 Security 上下文与 Spring Web 中用于处理异步请求映射的 WebAsyncManager 进行集成。

    2. SecurityContextPersistenceFilter:在每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中,然后在该次请求处理完成之后,将 SecurityContextHolder 中关于这次请求的信息存储到一个“仓储”中,然后将 SecurityContextHolder 中的信息清除,例如在Session中维护一个用户的安全信息就是这个过滤器处理的。

    3. HeaderWriterFilter:用于将头信息加入响应中。

    4. CsrfFilter:用于处理跨站请求伪造。

    5. LogoutFilter:用于处理退出登录。

    6. UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。默认情况下处理来自 /login 的请求。从表单中获取用户名和密码时,默认使用的表单 name 值为 username 和 password,这两个值可以通过设置这个过滤器的usernameParameter 和 passwordParameter 两个参数的值进行修改。

    7. DefaultLoginPageGeneratingFilter:如果没有配置登录页面,那系统初始化时就会配置这个过滤器,并且用于在需要进行登录时生成一个登录表单页面。

    8. BasicAuthenticationFilter:检测和处理 http basic 认证。

    9. RequestCacheAwareFilter:用来处理请求的缓存。

    10. SecurityContextHolderAwareRequestFilter:主要是包装请求对象request。

    11. AnonymousAuthenticationFilter:检测 SecurityContextHolder 中是否存在 Authentication 对象,如果不存在为其提供一个匿名 Authentication。

    12. SessionManagementFilter:管理 session 的过滤器

    13. ExceptionTranslationFilter:处理 AccessDeniedException 和 AuthenticationException 异常。

    14. FilterSecurityInterceptor:可以看做过滤器链的出口。

    15. RememberMeAuthenticationFilter:当用户没有登录而直接访问资源时, 从 cookie 里找出用户的信息, 如果 Spring Security 能够识别出用户提供的remember me cookie, 用户将不必填写用户名和密码, 而是直接登录进入系统,该过滤器默认不开启。

    先来看下面一个 Spring Security 执行流程图,只要把 SpringSecurity 的执行过程弄明白了,这个框架就会变得很简单

    image.png

    一个简单的流程

    1. 客户端发起一个请求,进入 Security 过滤器链。
    2. 当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 logoutSuccessHandler 登出成功处理,如果登出失败则由 ExceptionTranslationFilter ;如果不是登出路径则直接进入下一个过滤器。
    3. 当到 UsernamePasswordAuthenticationFilter 的时候判断是否为登录路径,如果是,则进入该过滤器进行登录操作,如果登录失败则到 AuthenticationFailureHandler 登录失败处理器处理,如果登录成功则到 AuthenticationSuccessHandler 登录成功处理器处理,如果不是登录请求则不进入该过滤器。
    4. 当到 FilterSecurityInterceptor 的时候会拿到 uri ,根据 uri 去找对应的鉴权管理器,鉴权管理器做鉴权工作,鉴权成功则到 Controller 层否则到 AccessDeniedHandler 鉴权失败处理器处理。

    # spring security扩展

    Security 可扩展的有

    • 鉴权失败处理器

      Security 鉴权失败默认跳转登录页面,我们可以实现 AccessDeniedHandler 接口,重写 handle() 方法来自定义处理逻辑;然后参考配置类说明将处理器加入到配置当中。

    • 验证器

      实现 AuthenticationProvider 接口来实现自己验证逻辑。需要注意的是在这个类里面就算你抛出异常,也不会中断验证流程,而是算你验证失败,我们由流程图知道,只要有一个验证器验证成功,就算验证成功,所以你需要留意这一点。

    • 登录成功处理器

      在 Security 中验证成功默认跳转到上一次请求页面或者路径为 "/" 的页面,我们同样可以自定义:继承 SimpleUrlAuthenticationSuccessHandler 这个类或者实现 AuthenticationSuccessHandler 接口。我这里建议采用继承的方式,SimpleUrlAuthenticationSuccessHandler 是默认的处理器,采用继承可以契合里氏替换原则,提高代码的复用性和避免不必要的错误。

    • 投票器

      投票器可继承 WebExpressionVoter 或者实现 AccessDecisionVoter接口;WebExpressionVoter 是 Security 默认的投票器;我这里同样建议采用继承的方式;添加到配置的方式参考 上文;

      注意:投票器 vote 方法返回一个int值;-1代表反对,0代表弃权,1代表赞成;投票管理器收集投票结果,如果最终结果大于等于0则放行该请求。

    • 自定义token处理过滤器

      自定义 token 处理器继承自 OncePerRequestFilter 或者 GenericFilterBean 或者 Filter 都可以,在这个处理器里面需要完成的逻辑是:获取请求里的 token,验证 token 是否合法然后填充 SecurityContextHolder ,虽然说过滤器只要添加在投票器之前就可以,但我这里还是建议添加在 http.addFilterAfter(new MyFittler(), LogoutFilter.class);

    • 登出成功处理器

      实现LogoutSuccessHandler接口,添加到配置的方式参考上文。

    • 登录失败处理器

      登录失败默认跳转到登录页,我们同样可以自定义。继承 SimpleUrlAuthenticationFailureHandler 或者实现 AuthenticationFailureHandler,建议采用继承。

    • 自定义 UsernamePasswordAuthenticationFilter

      我们自定义UsernamePasswordAuthenticationFilter可以极大提高我们 Security的灵活性(比如添加验证验证码是否正确的功能)。

      我们直接继承 UsernamePasswordAuthenticationFilter ,然后在配置类中初始化这个过滤器,给这个过滤器添加登录失败处理器,登录成功处理器,登录管理器,登录请求 url 。

    参考:

    • 深入了解Spring Security的实现原理 - 知乎 (zhihu.com) (opens new window)
    • Spring Security 工作原理概览_江南一点雨的专栏-CSDN博客 (opens new window)
    编辑 (opens new window)
    上次更新: 2021/04/07, 21:26:09
    spring MVC
    面试问题

    ← spring MVC 面试问题→

    Theme by Vdoing | Copyright © 2021-2021 小游
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式