Skip to content

认证流程与 AuthenticationManager

This content is not available in your language yet.

认证把未认证凭证转换成带权限的 Authentication,再由过滤器保存成功结果或转换失败。

先给答案:Provider 链把“凭证类型差异”隔离在认证策略内部

Section titled “先给答案:Provider 链把“凭证类型差异”隔离在认证策略内部”

AuthenticationManager 接收统一的认证请求,ProviderManager 再把它交给支持该 token 类型的 AuthenticationProvider。用户名密码、JWT、OAuth2、Remember-me 可以共享上层流程,却拥有不同的凭证解析和校验实现。

Provider 返回“不支持”、认证失败和认证成功的语义不同;异常处理器据此决定继续尝试、返回未认证还是拒绝。不要把“没有 provider 支持”和“凭证错误”混为一谈,它们对应不同的配置故障和安全响应。

credentials -> Authentication Filter
-> AuthenticationManager
-> ProviderManager
-> AuthenticationProvider(s)
-> SecurityContextRepository
  1. AbstractAuthenticationProcessingFilter#doFilter:web/.../AbstractAuthenticationProcessingFilter.java:237。
  2. 认证 matcher:web/.../AbstractAuthenticationProcessingFilter.java:328。
  3. manager 调用:web/.../AbstractAuthenticationProcessingFilter.java:363。
  4. 成功处理:web/.../AbstractAuthenticationProcessingFilter.java:392。
  5. 成功设置上下文:web/.../AbstractAuthenticationProcessingFilter.java:396。
  6. 失败处理:web/.../AbstractAuthenticationProcessingFilter.java:419。
  7. provider 遍历:core/.../ProviderManager.java:166、:183。
  8. parent 回退:core/.../ProviderManager.java:215。
  9. Basic 复用 manager:web/.../BasicAuthenticationFilter.java:204。

替代方案:一个 manager 写死密码、LDAP、JWT 等全部分支。 为什么不行:协议扩展会制造条件分支,应用也无法按需组合认证能力。 证据:ProviderManager 负责遍历,具体凭证逻辑下沉到 AuthenticationProvider。

场景 原因 规避
provider 顺序错误 未区分不支持与失败 正确实现 supports
成功后下一请求匿名 未保存 repository 使用成功处理器
每次请求查用户 没有持久化策略 选择 Session 或 JWT

Provider 链是能力路由模式,适合支付方式、编解码器和存储驱动选择。

面试锚点

  • 三个 Authentication 抽象如何分工?
  • 返回 null 和抛异常的区别?
  • 成功身份在哪里保存?