写点什么

Spring Security:用户和 Spring 应用之间的安全屏障

  • 2022 年 6 月 20 日
  • 本文字数:5038 字

    阅读完需:约 17 分钟

本文分享自华为云社区《【云驻共创】深入浅出Spring Security》,作者:香菜聊游戏。

前言

1.历史


Spring Security 最早叫 Acegi Security,这个名称并不是说它和 Spring 就没有关系,它依然是为 Spring 框架提供安全支持的。Acegi Security 基于 Spring,可以帮助我们为项目建立丰富的角色与权限管理系统。Acegi Security 虽然好用,但是最为人诟病的则是它臃肿繁琐的配置,这一问题最终也遗传给了 Spring Security。Acegi Security 最终被并入 Spring Security 项目中,并于 2008 年 4 月发布了改名后的第一个版本 Spring Security 2.0.0。


2.对比


和 Shiro 相比,Spring Security 重量级并且配置繁琐。其实自从 Spring Boot 推出后,就彻底颠覆了传统了 JavaEE 开发,自动化配置让许多事情变得非常容易。在一个 Spring Boot 项目中,我们甚至只需要引入一个依赖,不需要任何额外配置,项目的所有接口就会被自动保护起来了。在 Spring Cloud 中很多涉及安全管理的问题,也是一个 Spring Security 依赖两行配置就能搞定,在和 Spring 家族的产品一起使用时,Spring Security 的优势就非常明显了。因此在微服务时代,我们不需要纠结要不要学习 Spring Security,我们要考虑的是如何快速掌握 Spring Security,并且能够使用 Spring Security 实现我们微服务的安全管理。

3.为什么选择


不同于其他领域,在 Java 企业级开发中,安全管理方面的框架非常少,一般来说,主要有三种方案:


• 四郎

• 弹簧安全

• 开发者自己实现


Shiro 本身是一个老牌的安全管理框架,有着众多的优点,例如轻量、简单、易于集成,可以在 JavaSE 环境中使用等。不过在微服务面前,它无法充分展示自己的优势。也有开发者选择自己实现安全管理,不过一个系统的安全,不仅仅是登录和权限控制这么简单,我们还要考虑各种各样可能存在的网络攻击以及防御策略,从这个角度来说,只有大公司才有足够的人力物力去支持这件事情。Spring Security 作为 Spring 家族的一员,在和 Spring 家族的其他成员进行整合时,具有其他框架无可比拟的优势,同时对 OAuth2 有着良好的支持,再加上 Spring Cloud 对 Spring Security 的不断加持,让 Spring Security 成为微服务项目的首选安全管理方案。

1、Spring Security 简介


Spring Security 的核心功能


对于一个安全管理框架而言,无论是 Shiro 还是 Spring Security,最核心的功能,无非就是如下两方面认证和授权。

1.认证


认证就是身份验证(你是谁?),作为一个开放的平台,我们还可以通过引入第三方依赖来支持更多的认证方式,同时,如果这些认证方式无法满足我们的需求,我们也可以自定义认证逻辑,特别是当我们和一些"老破旧"的系统进行集成时,自定义 认证逻辑就显得非常重要了。

2.授权

授权就是访问控制(你可以做什么?),无论采用了哪种认证方式,都不影响在 Spring Security 中使用授权功能。Spring Security 支持基于 URL 的请求授权、支持方法访问授权、支持 SpEL 访问控制、支持域对象安全(ACL),同时也支持动态权限配置、支持 RBAC 权限模型等,总之我们常见的权限管理需求,Spring Security 基本上都是支持的。

3.其他

在认证和授权这两个核心功能之外,Spring Security 还提供了很多安全管理的“周边功能”,这也是一个非常重要的特色,例如:


• 密码加密

• 记住我

• 会话固定攻击防御

• CSRF 防御

• Http 防火墙

Spring Security 的整体架构


1.认证和授权


在 Spring Security 的架构设计中,认证(Authentication)和授权(Authorization)是分开的,无论使用什么样的认证方式,都不会影响授权,这是两个独立的存在,这种独立带来的好处之一,就是 Spring Security 可以非常方便地整合一些外部的认证方案。在 Spring Security 中,用户的认证信息主要由 Authentication 的实现类来保存,当用户使用用户名/密码登录或使用 Remember-me 登录时,都会对应一个不同的 Authentication 实例。Spring Security 中的认证工作主要是由 AuthenticationManager 接口来负责,在该接口中通过 authenticate 方法来做认证。AuthenticationManager 最主要的实现类是 ProviderManager,ProviderManager 管理了众多的 AuthenticationProvider 实例。在一次完整的认证流程中,可能会同时存在多个 AuthenticationProvider,多个 AuthenticationProvider 统一由 ProviderManager 来管理。同时,ProviderManager 具有一个可选的 parent,如果所有的 AuthenticationProvider 都认证失败,那么就会调用 parent 进行认证。

2.关键接口


在 Spring Security 的授权体系中,有两个关键接口: AccessDecisionManager 和 AccessDecisionVoter。


AccessDecisionVoter 是一个投票器,投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。


AccessDecisionManager 则是一个决策器,来决定此次访问是否被允许。

3.网络安全


在 Spring Security 中,认证、授权等功能都是基于过滤器来完成的。开发者所见到的 Spring Security 提供的功能,都是通过这些过滤器来实现的,这些过滤器按照既定的优先级排列,最终形成一个过滤器链。开发者也可以自定义过滤器,并通过 @Order 注解去调整自定义过滤器在过滤器链中的位置。需要注意的是,默认过滤器并不是直接放在 Web 项目的原生过滤器链中,而是通过一个 FilterChainProxy 来统一管理。


Spring Security 中的过滤器链通过 FilterChainProxy 嵌入到 Web 项目的原生过滤器链中。在 Spring Security 中,这样的过滤器链不仅仅只有一个可能会有多个。当存在多个过滤器链时,多个过滤器链之间要指定优先级,当请求到达后,会从 FilterChainProxy 进行分发,先和哪个过滤器链匹配上,就用哪个过滤器链进行处理。


2、弹簧认证流程分析

1.基本认证


在 Spring Boot 项目中使用 Spring Security 非常方便,创建一个新的 SpringBoot 项目,我们只需要引入 web 和 Spring Security 依赖即可。


Maven 项目加入下面的依赖



引入依赖后,项目中的所有接口就都被保护起来了,此时访问接口就可以看到登录页面了。


2.Spring Security 认证流程分析



AuthenticationManafer 是一个认证管理器。它定义了 Spring Security 过滤器要如何执行认证操作,在认证成功后,会返回一个 Authentication 对象,这个对象会被设置到 SecurityContextHodler 中。AuthenticationManafer 是一个接口,它有着诸多的实现类,开发者可以自定义 AuthenticationManafer 的实现类,不过在实际应用中,我们使用最多的是 ProviderManager,在 Spring Security 框架中,默认也是使用 ProviderManager。

1)身份验证提供商


Spring Security 支持多种不同的认证方式,不同的认证方式对应不同的身份类型,AuthentucationProvider 就是针对不同的身份类型执行具体的身份认证。例如,常见的 DaoAuthenticationProvider 用来支持用户名密码登录认证, RememberMeAuthenticationProvider 用来支持记住我的认证。

2)供应商经理


在 Spring Security 中,由于系统可能同时支持多种不同的认证方式,例如同时支持用户名/密码认证、RememberMe 认证、手机号码动态认证等,而不同的认证方式对应了不同的 AuthenticationProvider,所以一个完整的认证流程可能由多个 AuthenticationProvider 来提供。多个 AuthenticationProvider 将组成一个列表这个列表将由 ProviderManagerf 代理。换句话说,在 ProviderManager 中存在一个 AuthenticationProvider 表在 ProviderManager 中遍历列表中的每一个 AuthenticationProvider 去执行身份认证,最终得到认证结果。ProviderManager 本身也可以再配置一个 AuthenticationManager 作为 parent,这样当 ProviderManager 认证失败之后,就可以进入到 parent 中再次进行认证。理论上来说,ProviderManager 的 parent 可以是任意类型的 AuthenticationManager,但是通常都是由 ProviderManager 来扮演 parent 的角色,也就是 ProviderManager 是 ProviderManager 的 parent。


3)抽象认证处理过滤器


摘要 AuthenticationProcessingFilter 用来处理任何提交给它的身份认证。


3、弹簧安全密码加密

1.常见实现类


BcryptPasswordEncoder

Argon2PasswordEncoder

Pbkdf2PasswordEncoder

ScryptPasswordEncoder

2.委托密码编码器


DelegatingPasswordEncoder 是一个代理类,而并非一种全新的密码加密方案。主要用来代理不同的密码加密方案。为什么采用而不是某一个具体加密方式作为默认的密码加密方案呢?主要考虑了如下三方面的因素:


(1)兼容性:使用 DelegatingPasswordEncoder 可以帮助许多使用旧密码加密方式的系统顺利迁移到中,它允许在同一个系统中同时存在多种不同的密码加密方案。


(2)便捷性:密码存储的最佳方案不可能一直不变,如果使用 DelegatingPasswordEncoder 作为默认的密码加密方案,当需要修改加密方案时,只需要修改很小一部分代码就可以实现。


(3)稳定性:作为一个框架,不能经常进行重大更改,而使用 DelegatingPasswordEncoder 可以方便地对密码进行升级(自动从一个加密方案升级到另外一个加密方案)。

4、春季安全会话管理

1.什么是会话


当浏览器调用登录接口登录成功后,服务端会和浏览器之间建立一个会话(Session),浏览器在每次发送请求时都会携带一个 SessionId,服务端则根据这个 SessionId 来判断用户身份。当浏览器关闭后,服务端的 Session 并不会自动销毁,需要开发者手动在服务端调用 Session 销毁方法,或者等 Session 过期时间到了自动销毁。在 Spring Security 中,与 HttpSession 相关的功能由 SessionManagementFilter 和 SessionAuthenticationStrategy 接口来处理, 过滤器将 Session 相关操作委托给 SessionAuthenticationStrategy 接口去完成。

2.什么是会话并发管理?


会话并发管理就是指在当前系统中,同一个用户可以同时创建多少个会话,如果一台设备对应一个会话,那么也可以简单理解为同一个用户可以同时在多少台设备上进行登录。默认情况下,同一用户在多少台设备上登录并没有限制,不过开发者可以在 Spring Security 中对此进行配置。

3.挤下线


当会话并发数达到限制时,新的会话将之前旧的会话挤下线,旧的登录会话失效。配置如下


4.限制登录

当会话并发数达到限制时,新的会话将被限制创建,除非旧的会话主动退出登录。


5.什么是会话固定攻击


会话固定攻击(Session fixation attacks)是一种潜在的风险,恶意攻击者有可能通过访问当前应用程序来创建会话,然后诱导用户以相同的会话登录(通常是将会话作为参数放在请求链接中,然后诱导用户去单击),进而获取用户的登录身份。

1.会话固定攻击步骤


(1)攻击者自己可以正常访问 javaboy 网站,在访问的过程中,网站给攻击者分配了一个。


(2)攻击者利用自己拿到的 sessionId 构造一个 javaboy 网站的链接,并把该链接发送给受害者。


(3)受害者使用该链接登录 javaboy 网站(该链接中含有 sessionId),登录成功后,一个合法的会话就成功建立了。


(4)攻击者利用手里的冒充受害者。

2.会话固定攻击防御策略


Spring Security 中从三方面入手防范会话固定攻击:


(1)Spring Security 中默认自带了 Http 防火墙,如果 sessionId 放在地址栏中,这个请求就会直接被拦截下来。


(2)在 http 响应的 Set-Cookie 字段中有 HttpOnly 属性,这样避免了通过 XSS 攻击来获取 Cookie 中的会话信息, 进而达成会话固定攻击。


(3)在用户登录成功后,改变 SessionId, Spring Security 中默认实现了该种方案。

5、弹簧安全防火墙

1.什么是防火墙


HttpFirewall 是 Spring Security 提供的 Http 防火墙,它可以用于拒绝潜在的危险请求或者包装这些请求进而控制其行为。通过可以对各种非法请求提前进行拦截并处理,降低损失。

2.Spring Security 中的 HttpFirewall 两个实现类



• DefaultHttpFirewall 虽然名字中包含 Default,但这并不是框架默认使用的 Http 防火墙,它只是一个检查相对宽松的防火墙。


HttpFirewall 普通模式就是使用 DefaultHttpFirewall,该类的校验规则就要简单很多。一般来说,并不建议开发者在项目中使用 DefaultHttpFirewall,因为相比于 StrictHttp Firewal,DefaultHttpFirewall 的安全性要差很多。


• StricHttpFirewall 这是一个检查严格的 Http 防火墙,也是框架默认使用的 http 防火墙

严格模式下对请求做出了诸多限制:


1) rejectForbiddenHttpMethod:校验请求方法是否合法。

2)RejectedBlacklistedUrls:校验请求中的非法字符。

3) RejectedUntrustedHosts:检验主机信息。

4)isNormalized:判断参数格式是否合法。

5)containonlyPrintableAsciCharacters: 判断请求字符是否合法。

总结


Spring Security 是一个安全框架,作为 Spring 家族的一员,可以简单地认为 Spring Security 是放在用户和 Spring 应用之间的一个安全屏障,每一个 web 请求都先要经过 Spring Security 进行 Authenticate 和 Authoration 验证,其核心就是一组过滤器链。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
Spring Security:用户和Spring应用之间的安全屏障_安全_华为云开发者联盟_InfoQ写作社区