解锁Spring Security6:核心安全机制

结合 Spring Security 官网,简单和小伙伴们聊一聊 Spring Security 架构。

应用程序安全可以归结为两个问题:

  1. 认证(你是谁?)
  2. 授权(你被允许做什么?)

Spring Security 设计了一个架构,旨在将认证与授权分离,并为两者都提供了策略和扩展点。

一 认证

认证的主要接口是 AuthenticationManager,它只有一个方法:

public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication)
        throws AuthenticationException
;
}

一个 AuthenticationManager 在它的 authenticate() 方法中可以做三件事:

  • 如果它能验证输入表示一个有效的用户,则返回一个Authentication(通常带有authenticated=true)。
  • 如果它认为输入表示一个无效的用户,则抛出一个AuthenticationException
  • 如果它无法决定,则返回 null

AuthenticationManager 最常用的实现是 ProviderManager,它委托给一系列 AuthenticationProvider 实例。

一个 AuthenticationProvider 有点像一个 AuthenticationManager,但它有一个额外的方法,允许调用者查询它是否支持给定的 Authentication 类型:

public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication)
        throws AuthenticationException
;

    boolean supports(Class<?> authentication);
}

supports() 方法中的 Class<?> 参数实际上是 Class<? extends Authentication>,一个 ProviderManager 可以通过委托给一系列 AuthenticationProviders 来支持同一应用程序中的多种不同的认证机制。如果 ProviderManager 不认识特定的 Authentication 实例类型,它就会被跳过。

ProviderManager 有一个可选的父级,如果所有提供者都返回 null,那么认证操作会委托给父级去完成,父级也可以有父级,父级如果不存在或者认证失败,那么最终就认证失败。

下面这张图展示了 ProviderManagerAuthenticationManager的层次结构:

img

如上图,应用程序有一组受保护的资源,例如 /api/**,每个组都可以有自己专用的 AuthenticationManager。通常情况下,每个组都是一个 ProviderManager,并且它们共享一个父级。然后,父级就是一种“全局”资源,作为所有提供者的后备。

当然,接下来是第二部分的翻译:

二 安全性

Spring Security 在 Web 层级(用于用户界面和 HTTP 后端)基于 Servlet Filters,因此首先了解 Filters 的角色会有所帮助。下图展示了单个 HTTP 请求的处理器典型层级结构。

img

客户端向应用程序发送请求,容器根据请求 URI 的路径决定应用哪些过滤器和 Servlet。一个 Servlet 可以处理一个请求,但过滤器形成链,因此它们是有序的。

实际上,如果过滤器想要处理请求,它可以否决链中剩余的部分(提前终止)。过滤器还可以修改下游过滤器。过滤器链的顺序非常重要,Spring Boot 通过两种机制管理它:

  1. @Beans 类型为 Filter 可以有 @Order 注解或实现 Ordered 接口,并且它们可以是 FilterRegistrationBean 的一部分,后者本身在其 API 中具有顺序。
  2. 一些默认的过滤器定义了它们自己的顺序常量,例如,来自 Spring Session 的 SessionRepositoryFilter 有一个 DEFAULT_ORDERInteger.MIN_VALUE + 50,这告诉我们它喜欢在链中早期出现,但它不排除其他过滤器在它之前出现。

Spring Security 作为链中的单个 Filter 安装,其具体类型是 FilterChainProxy。在 Spring Boot 应用程序中,安全过滤器是 ApplicationContext 中的 @Bean,默认情况下会被自动加载,以便应用于每个请求。它加载在由 SecurityProperties.DEFAULT_FILTER_ORDER 定义的位置,该位置又由 FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER 锚定。

从 Tomcat 容器的角度来看,Spring Security 是一个单独的过滤器,但在 Spring Security 内部,还有额外的过滤器,每个过滤器都扮演着特殊的角色。下图展示了这种关系:

img

实际上,在安全过滤器中还有一层间接性:它通常作为 DelegatingFilterProxy 加载在 Tomcat 容器中,它不必是 Spring @BeanDelegatingFilterProxy 会把接收到的请求委派给一个  FilterChainProxy

可以有多个由 Spring Security 在同一个顶级 FilterChainProxy 中管理的过滤器链,所有这些都对容器未知。Spring Security 过滤器包含了一个过滤器链列表,并将请求分派给第一个匹配的链。下图显示了基于请求路径匹配(/foo/**/** 之前匹配)的分派。这是非常常见的,但不是匹配请求的唯一方式,分派过程最重要的特性是,只有一个链曾经处理过请求。

img

例如手机 App 登录可以不用考虑 CSRF 跨站请求伪造,但是 Web 端登录则要考虑,跨站请求伪造由 CsrfFilter 负责防御,那么我们就可以利用这个能力,对来自手机的请求 /phone/** 和来自 Web 的请求 /web/** 分别用不同的过滤器链处理。

注意:Spring Security 内部的所有过滤器对容器都是不可见的,这很重要,特别是在 Spring Boot 应用程序中,因为在 Spring Boot 中,默认情况下,所有类型为 Filter@Bean 都会自动注册到容器中。因此,如果您想将自定义过滤器添加到安全链中,您需要要么不让它成为 @Bean,要么将其包装在 FilterRegistrationBean 中。

Spring Security 博大精深,如果小伙伴们想要彻底掌握 Spring Security,那么不妨看看我最近新出的一套 Spring Security 视频教程。

最新版 Spring Security + OAuth2 视频杀青啦!

不废话,先来看目录:

基本上把 Spring Security 的方方面面以及 OAuth2 都讲到了。最重要的是,贴合了很多小伙伴们日常常见的开发场景,比如短信验证码登录,微信 OAuth2 登录等等都有讲到。

这套视频是基于目前最新版的 Spring Security6 录制的,Spring Security6 在 API 层面的变化还是蛮大的,引入了大量的 Lambda 表达式去简化配置,很多旧版的写法在 Spring Security6 中被废弃,并在将来在 Spring Security7 中会移除相关的 API,所以说最近的 Spring Security 更新还是蛮激进的。

另一方面就是这套视频包含了全新的基于目前最新版 Spring Security 录制的 OAuth2 教程,松哥在 2020 年的时候出过图文版的 OAuth2 教程,但是,现在新版的 OAuth2 也有很多变化,不仅仅是 API 层面的变化,授权模式也发生了一些变化,传统的密码模式、简化模式现在都不再支持,转而引入了 PKCE 模式,并且利用 OIDC 简化用户信息获取。同时,在 2020 年还处于萌芽状态的 Spring Security OAuth2 Server 这个项目,目前也趋于成熟,也可以直接使用了,这些松哥都在视频中和大家做了详细介绍。在 OAuth2 环节我也和大家分享了如何使用微信的 OAuth2 登录。

总之这一套教程,让大家彻底理解系统的安全管理。

之前有小伙伴说我直接自己写过滤器,既灵活还简单。我并不反对这种做法,但是有一个前提就是你很牛,你自己写的过滤器有考虑到计时攻击,有考虑到 XSS 攻击,有考虑到点击劫持,有考虑跨站请求伪造。。。等等太多了。当然,这些问题如果你都没有考虑到,那么 Spring Security 都有帮你考虑到并提供解决方案!

理解了 Spring Security,再去看市面上其他的安全管理框架,都会豁然开朗。

这套教程目前给小伙伴们提供了一个试看视频:

这套视频是付费的,¥499,有需要的小伙伴加微信备注 499,五一假期正好操练起来。


相关推荐

  • 独家资料下载:《大模型推荐系统》
  • 微信成对数据AB实验探索
  • 百度推荐资源冷启动实践
  • 金山办公姚冬:AI让办公不再孤立,LUI是下一代交互 | 中国AIGC产业峰会
  • 小心!最新AI看一眼照片就定位你在哪里,精确到经纬度
  • 70亿LLaMA媲美5400亿PaLM!MIT惊人研究用「博弈论」改进大模型|ICLR 2024
  • 史上最丑AI生图一夜爆火!又一款妙鸭级爆品来了?
  • OpenAI谷歌苹果再燃AI争霸战,谁将担纲「Her」时代王者?
  • AlphaFold 3轻松应对核酸、脂类分子?科学家迫不及待地更新了评测
  • Flash Attention稳定吗?Meta、哈佛发现其模型权重偏差呈现数量级波动
  • 从零开始手搓GPU,照着英伟达CUDA来,只用两个星期
  • DiT架构大一统:一个框架集成图像、视频、音频和3D生成,可编辑、能试玩
  • 2024最佳 React UI 库盘点
  • Node.js 22发布,增强了对ESM模块和Web API的支持
  • “我们坚持开源!”阿里云发布“地表最强”中文大模型:半年一迭代、性能翻倍?
  • 大模型永远也不做了的事情是什么?
  • “国外一开源,国内就创新”!面对中美大模型差异,我们该突破还是继续模仿?
  • Java开发杀手级框架!!
  • 10张图,搞定MySQL隔离级别
  • 同事说,这是写ChatGPT Prompt的万能公式