Spring Boot 与 Spring Security OAuth 2.0 实现 SSO(单点登录),一文轻松带你搞定!

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8
概述
随着企业信息化系统的逐步发展,越来越多的企业开始采用微服务架构。微服务架构下,每个服务通常都是独立部署的,涉及多个系统间的服务通信和数据共享,而单点登录(SSO)作为一种集中式身份认证机制,能够为用户提供便利,只需一次登录就可以访问多个应用系统。SSO 的应用能够极大提高用户体验,减少多次身份验证的繁琐过程。
Spring Boot 与 Spring Security 结合 OAuth 2.0 提供了一种强大而灵活的方式来实现 SSO。OAuth 2.0 是目前非常流行的开放授权协议,它不仅可以帮助我们实现认证(Authentication)功能,还能有效地进行权限控制(Authorization)。结合 OAuth 2.0 的授权码授权、JWT(JSON Web Token)令牌的安全机制,我们可以为多种类型的应用系统提供统一的身份认证和访问控制方案。
本文将详细介绍如何使用 Spring Boot 和 Spring Security 配合 OAuth 2.0 来实现单点登录(SSO)。我们将探讨 OAuth 2.0 协议的基础、Spring Boot 配置认证服务器、实现 JWT Token 存储与校验、配置跨域认证与安全问题等内容。
目录
- 🔑 OAuth 2.0 协议概述与在 SSO 中的应用
- 🛠️ Spring Boot 配置 OAuth 2.0 认证服务器支持 SSO 功能
- 🛡️ 基于 JWT 的 Token 存储与校验机制,保障 SSO 的安全性
- 🌐 配置多服务的跨域认证,通过 OAuth 2.0 授权服务器共享认证信息
- 🔒 SSO 中的安全性问题:Token 过期、刷新机制与权限控制
- 🔧 SSO 与多租户环境下的适配
- 💡 总结与展望
- 🔍 延伸阅读与最佳实践
1. 🔑 OAuth 2.0 协议概述与在 SSO 中的应用
OAuth 2.0 协议
OAuth 2.0 是一种开放的授权协议,它允许用户授权第三方应用在不暴露用户密码的情况下,访问用户在其他服务上的资源。OAuth 2.0 适用于处理授权和认证问题,但它本身并不解决身份认证问题。为了处理身份认证问题,OAuth 2.0 可以与 OpenID Connect(OIDC)结合使用,OIDC 在 OAuth 2.0 的基础上引入了身份验证功能,提供了更强大的支持。
OAuth 2.0 协议有多个授权模式,常见的有:
- 授权码模式(Authorization Code Grant):最安全的授权模式,通常用于 Web 应用程序。用户通过浏览器重定向到授权服务器,授权完成后,返回授权码,客户端使用授权码请求访问令牌。
- 简化模式(Implicit Grant):主要用于 JavaScript 客户端应用,直接返回访问令牌,但不推荐用于涉及敏感数据的场景,因为令牌容易暴露。
- 密码模式(Password Grant):直接使用用户名和密码获取访问令牌,适用于信任度较高的客户端。
- 客户端凭证模式(Client Credentials Grant):用于应用间的机器对机器通信,通过客户端凭证直接获取访问令牌。
OAuth 2.0 在 SSO 中的应用
在单点登录(SSO)系统中,OAuth 2.0 作为认证协议能够为用户提供统一的身份认证。用户只需要在认证服务器进行一次身份验证,之后系统通过共享的访问令牌(Access Token)允许用户访问不同的微服务。
通过 OAuth 2.0 的授权码模式,用户只需登录一次,认证服务器会发放一个授权码,并在认证流程完成后为用户生成访问令牌,用户可使用该令牌访问其他服务。OAuth 2.0 的授权服务器充当认证服务的角色,而资源服务器则存储用户数据和应用数据。
OAuth 2.0 实现 SSO 的流程如下:
- 用户访问应用A。
- 应用A检查是否已认证,若未认证,重定向用户到授权服务器。
- 用户在授权服务器登录,授权后返回授权码。
- 应用A通过授权码请求访问令牌(Access Token)。
- 用户再次访问应用B,应用B通过OAuth 2.0 的授权服务器验证令牌,允许用户访问资源。
2. 🛠️ Spring Boot 配置 OAuth 2.0 认证服务器支持 SSO 功能
配置 OAuth 2.0 认证服务器
为了实现 SSO,我们需要在 Spring Boot 中配置一个 OAuth 2.0 认证服务器。Spring Security 提供了对 OAuth 2.0 的完整支持,能够帮助我们快速搭建认证服务器。首先,我们需要添加 Spring Security OAuth 2.0 相关的依赖。
添加依赖
在 pom.xml 中添加 OAuth 2.0 认证服务器相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.2.0</version>
</dependency>
认证服务器配置
接下来,配置一个 OAuth 2.0 认证服务器。我们需要使用 AuthorizationServerConfigurerAdapter 类,配置授权服务器的安全设置、客户端详细信息和授权方式。
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.secret("{noop}secret")
.redirectUris("http://localhost:8081/login/oauth2/code/custom")
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("read", "write");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore);
}
}
上述配置定义了客户端的基本信息、授权码授权流程以及令牌存储方式(在本例中使用内存存储)。
3. 🛡️ 基于 JWT 的 Token 存储与校验机制,保障 SSO 的安全性
JWT(JSON Web Token)
JWT 是一种开放标准,它用于在应用间安全地传输声明信息。JWT 通常由三个部分组成:
- Header:包含令牌类型(JWT)以及使用的签名算法(如 HS256)。
- Payload:有效载荷,包含用户信息、权限等数据。
- Signature:签名部分,用于验证数据的完整性。
在 OAuth 2.0 的认证服务器中,JWT 用作访问令牌(Access Token)。通过加密签名,JWT 令牌可以保证数据的完整性,并且可以在不同的应用间安全地传递。
Spring Boot 配置 JWT 令牌
为了在 Spring Boot 中实现 JWT,我们可以使用 JwtEncoder 和 JwtDecoder 来生成和验证 JWT 令牌。
JWT 配置类
@Configuration
public class JwtConfig {
@Value("${jwt.secret}")
private String secretKey;
@Bean
public JwtDecoder jwtDecoder() {
return JwtDecoder.withSecretKey(secretKey).build();
}
@Bean
public JwtEncoder jwtEncoder() {
return JwtEncoder.withSecretKey(secretKey).build();
}
}
JWT 认证过滤器
JWT 认证过滤器可以帮助我们验证请求中的 JWT 令牌是否有效,确保请求是由已认证的用户发出的。
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtDecoder jwtDecoder;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String jwtToken = request.getHeader("Authorization");
if (jwtToken != null && jwtToken.startsWith("Bearer ")) {
String token = jwtToken.substring(7);
try {
Jwt jwt = jwtDecoder.decode(token);
// Set authentication context
SecurityContextHolder.getContext().setAuthentication(new JwtAuthenticationToken(jwt));
} catch (JwtException e) {
// Handle invalid token
}
}
filterChain.doFilter(request, response);
}
}
在这个过滤器中,JWT 令牌从请求头部提取并解码。如果令牌有效,将会设置认证信息到安全上下文中。
4. 🌐 配置多服务的跨域认证,通过 OAuth 2.0 授权服务器共享认证信息
跨域认证
在微服务架构中,应用系统通常是分布式部署的,可能存在跨域访问的需求。OAuth 2.0 和 Spring Security 为我们提供了跨域认证的解决方案。
配置跨域认证
Spring Security 可以通过 CORS(跨域资源共享)来解决跨域认证问题。我们可以在认证服务器的配置中启用 CORS 支持,允许多个服务共享认证信息。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8081", "http://localhost:8082")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("Authorization", "Content-Type");
}
}
通过配置 CORS,客户端可以通过跨域请求访问认证服务器,获取有效的访问令牌。
5. 🔒 SSO 中的安全性问题:Token 过期、刷新机制与权限控制
Token 过期与刷新机制
在 SSO 中,访问令牌通常会设置过期时间,防止令牌被长期使用。如果令牌过期,用户需要重新认证。为了提高用户体验,OAuth 2.0 使用刷新令牌(Refresh Token)机制,允许用户在令牌过期后通过刷新令牌获取新的访问令牌。
刷新令牌配置
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.reuseRefreshTokens(false);
}
通过配置 reuseRefreshTokens(false),我们可以确保每次使用刷新令牌时,系统都会为用户颁发一个新的访问令牌。
权限控制
在 SSO 中,用户的权限通常是通过角色、权限等信息来管理的。Spring Security 提供了基于角色的权限控制机制,可以通过注解如 @PreAuthorize 或 @Secured 来实现方法级权限控制。
@PreAuthorize("hasRole('ADMIN')")
public void accessAdminDashboard() {
// Only accessible by users with 'ADMIN' role
}
通过这种方式,系统可以根据用户的角色或权限来限制对特定资源的访问。
6. 🔧 SSO 与多租户环境下的适配
在多租户环境中,SSO 的实现不仅要考虑跨多个服务的认证,还要处理每个租户的身份隔离问题。为了在多租户架构中实现 SSO,可以使用 OAuth 2.0 和租户上下文来确保每个租户的身份信息是独立的。
租户上下文管理
租户上下文可以通过 ThreadLocal 或其他方式在认证过程中设置和获取。确保每个租户在 SSO 流程中都有独立的认证信息。
public class TenantContext {
private static final ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setTenant(String tenantId) {
currentTenant.set(tenantId);
}
public static String getTenant() {
return currentTenant.get();
}
}
7. 💡 总结与展望
单点登录(SSO)为分布式应用提供了便利的用户认证方案,减少了用户重复登录的繁琐。在微服务架构中,结合 Spring Boot 和 OAuth 2.0,我们可以轻松实现集中式身份验证,确保跨多个服务的数据一致性和安全性。
未来,随着企业应用规模的扩大和云原生架构的兴起,SSO 将越来越成为企业应用的标配。在 SSO 的实现过程中,如何处理安全性、性能和扩展性等问题将是设计的关键。通过合理配置 OAuth 2.0 认证服务器、JWT 令牌和权限控制,开发者可以为用户提供一个安全、便捷且无缝的身份验证体验。
8. 🔍 延伸阅读与最佳实践
- OAuth 2.0 与 OpenID Connect:深入学习 OAuth 2.0 和 OpenID Connect 的认证与授权机制。
- Spring Security 深入:探索 Spring Security 的认证与授权机制,学习如何实现细粒度的权限控制。
- JWT 安全最佳实践:了解 JWT 的工作原理及如何保护 JWT 令牌免受攻击。
- Spring Cloud Security:了解如何在微服务架构中使用 Spring Cloud Security 实现跨服务的认证与授权。
🧧福利赠与你🧧
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。
✨️ Who am I?
我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-
- 点赞
- 收藏
- 关注作者
评论(0)