一、开篇:Spring Security是什么?
Spring Security OAuth 2.0框架长久以来一直是开发者们在构建安全的应用程序时的得力助手,其核心功能是为客户端应用提供一个稳健的安全上下文以及认证与授权的机制。通过OAuth 2.0,第三方应用可以安全地获取用户的授权,从而访问其受保护的资源。
然而,随着网络身份验证技术的演进,OpenID Connect 1.0逐渐成为了行业的新标准。OpenID Connect不仅支持OAuth 2.0的授权流程,还增加了用户身份验证和用户信息交互的功能,这意味着它除了能提供访问权限外,还可以用来确认用户的身份,并提供用户的基本信息。这一功能在很多现代应用中变得尤为重要,比如单点登录(SSO)场景。
为了满足开发者对OpenID Connect支持的需求,以及简化用户会话管理的复杂性,Spring Security团队在版本5.2中初步集成了OpenID Connect的功能。这一举措显示出Spring Security对于新技术和市场需求的敏感度和适应性。随着技术逐步演进,Spring Security在6.0版本中迈出了更大的一步,正式引入了spring-security-oauth2-authorization-server模块。这个全新的模块不仅符合OAuth 2.0的严格规范,还完全兼容OpenID Connect 1.0的标准。通过这个模块,开发者可以轻松地搭建起一个功能完备的OAuth 2.0授权服务器,并利用OpenID Connect进行身份验证和获取用户信息。
[挺重要的一个观点] spring-security-oauth2-authorization-server模块的引入还简化了用户会话管理的复杂性。通过OpenID Connect,应用不仅可以进行安全的授权,还能管理用户的登录会话,提供单点登录等高级功能,这对于提升用户体验和系统安全性都是至关重要的,
我们开始进入这个安全框架的初步探索,我们一起揭开这一层神秘的面纱,聊一聊企业级里面怎么应用它们。
二、Spring Security 6.0更新了什么核心技术?
- 配置方式的变更:Spring Security 6.0采用了基于Lambda表达式的DSL配置方式,取代了之前的纯链式调用方式,使得配置更加灵活和直观。例如,
antMatchers被替换为requestMatchers3。 - 废弃和移除不安全/已弃用的功能:为了提高安全性,Spring Security 6.
- 过滤器的重新组织:将过滤器移动到Web包中并重新组织导入,这是对现有架构的一次重大调整 2。
- 支持新的认证协议:引入了对OAuth 2.1和OpenID的支持,这表明Spring Security在适应现代身份验证需求方面迈出了重要一步 1。
- 默认配置的提供:除了Spring Boot的专有配置外,Spring Security自身也提供了默认配置,这些默认配置旨在简化开发者的配置工作 3。
- 版本兼容性和破坏性更新:虽然引入了许多破坏性的更新,包括废弃代码的删除、方法重命名以及全新的配置DSL等,但架构和基本原理保持不变,确保了向后兼容性 10。
- 更新安全上下文中的身份验证令牌:这一更新涉及到安全上下文中的身份验证令牌的更新,是Spring Security在维护用户会话管理方面的一个重要改进 11。
- 文档的改进:Spring Security 6.0还包括了对文档的修复和改进,帮助开发者更好地理解和使用新版本 12。
- 移除WebSecurityConfigurerAdapter 在Spring Security 6.0中,移除WebSecurityConfigurerAdapter配置类的影响主要体现在需要开发者改变原有的安全配置方式。WebSecurityConfigurerAdapter是一个用于自定义HTTP安全性的类,允许通过继承该类来自定义如端点授权或Authentication Manager配置等612。然而,在Spring Security的最新版本中,这个类已经被弃用,并且在5.7版本中被标记为@Deprecated,最终在6.0版本中被完全移除。替代方案主要包括使用SecurityFilterChain来替代WebSecurityConfigurerAdapter的功能。SecurityFilterChain是一个新的类,它的作用是代替了WebSecurityConfigurerAdapter的configure方法,从而不需要再去实现WebSecurityConfigurerAdapter2。
针对以上第9点,我们可以这么去配置,这是一种新的玩法:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain() {
return http()
.authorizeHttpRequests((授权请求) -> {
许可策略();
})
.build();
}
}
这种新的配置方式不仅提供了更高的灵活性,还使得代码更加简洁易读。同时,这也符合Spring Security向组件化和声明式配置演进的趋势,移除WebSecurityConfigurerAdapter对开发者来说是一个较大的变化,需要适应新的配置方式。但通过使用SecurityFilterChain和Lambda表达式,可以有效地实现这一过渡,并利用Spring Security的新特性来增强应用的安全性。
三、有必要科普一下OAuth 2.0和OpenID Connect 1.0,它们是谁?
OAuth 2.0协议 OAuth 2.0是一种授权协议,全名为“开放授权2.0”(Open Authorization 2.0),它允许第三方应用程序访问用户在另一个服务提供者上的资源,而无需共享用户的凭据(例如用户名和密码)1。OAuth 2.0主要用于授权访问,而不是认证用户身份。OAuth 2.0的设计旨在简化客户端开发者的复杂性,同时为不同的应用场景提供了特定的授权流程,如Web应用程序、桌面应用程序、移动电话和平板电脑等。
OpenID Connect 1.0协议 OpenID Connect 1.0是在OAuth 2.0协议基础上增加的一个身份验证层。它扩展了OAuth 2.0的功能,不仅允许第三方应用访问资源,还提供了验证终端用户身份的能力3。OpenID Connect 1.0使得客户端可以基于授权服务的鉴权能力来验证及识别终端用户的身份5。这意味着,除了访问资源的权限外,OpenID Connect还能提供关于用户的基本信息,如姓名、电子邮件地址等。
总体来说,OAuth 2.0主要关注于如何安全地授权第三方应用访问用户存储在其他服务提供者上的资源,而OpenID Connect 1.0则在此基础上增加了身份验证层,使得客户端能够验证用户的身份,并获取用户的简要信息。这两个协议共同为现代企业级应用中的身份验证和授权提供了强大的支持。
在企业级应用级方面,通过结合使用OAuth 2.0和OpenID Connect 1.0,企业可以实现单点登录系统。这意味着用户只需一次登录即可访问所有受保护的资源,极大地提升了用户体验和工作效率。
四、在SpringBoot中如何配置使用
- 增加maven依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>6.2.4</version>
<scope>test</scope>
</dependency>
- 启用配置类
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.exceptionHandling(e -> e.authenticationEntryPoint(new UnAuthorizedEntryPoint()));
http.oauth2ResourceServer(
(resourceServer) ->
resourceServer.jwt(jwt -> jwt.jwtAuthenticationConverter(customJwtConverter)));
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(Customizer.withDefaults())
.authorizeHttpRequests(
request ->
request
.requestMatchers(new AntPathRequestMatcher("/oauth/**"))
.permitAll()
.requestMatchers(new AntPathRequestMatcher("/public/**"))
.permitAll()
.anyRequest()
.authenticated())
.sessionManagement(
session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.cors(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(Customizer.withDefaults());
return http.build();
}
/**
* 用于配置Spring Security OAuth2授权配置信息;
*
* @return AuthorizationServerSettings
*/
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder()
.authorizationEndpoint("/oauth/authorize")
.tokenEndpoint("/oauth/token")
.tokenRevocationEndpoint("/oauth/revoke")
.build();
}
- 验证授权接口
确保通过浏览器或其他客户端工具(POSTMAN)测试OAuth 2.0登录流程是否正常工作。检查用户是否能够成功登录并被授权访问受保护的资源。
五、总结 & 最佳实践建议
- 实施合适的令牌过期策略:通过实施合适的令牌过期策略,可以减少令牌泄露的风险
- 选择合适的授权模式:根据具体的应用场景和安全需求,选择最合适的OAuth 2.0授权模式。例如,授权码(authorization_code)模式是目前流程最完备、安全性最高的授权流程。
- 支持多客户端配置:在内存或Redis等存储方式下,支持多种方式存储认证信息以及客户端信息,以适应不同的业务需求.
- 虑PKCE扩展:为了增强安全性,可以考虑使用PKCE(Proof Key for Code Exchange)扩展,它要求在请求授权码时提供额外的code_challenge和code_verifier,从而增加了攻击者获取授权码的难度.
- 使用HTTPS保护通信:为了确保授权过程中的所有通信都是安全的,应始终使用HTTPS协议.
- 单点登录(SSO)的实现:Spring Cloud Security支持JWT和OAuth 2.0,可以用来实现单点登录。这允许用户在首次登录到任一服务时进行一次身份验证,之后便可以在整个系统内无需重复登录.
- 认证授权中心的搭建:在微服务架构规划时,首先需要构建一个认证授权中心服务,这个中心负责处理用户的认证和授权请求。可以使用Spring Security OAuth2来实现这一功能,它支持多种授权模式,如资源所有者模式、密码凭证模式等
以上为全文,谢谢。