单点登录(Single Sign-On, SSO)是一种让用户在多个应用系统之间只需登录一次就可以访问所有授权系统的机制。单点登录主要目的是为了提高用户体验并简化安全管理。
举个例子,您在一个大型企业工作,该企业拥有一套由多个独立应用程序组成的生态系统,例如:内部邮箱系统、项目管理系统、员工自助服务系统、人力资源信息系统等。
而这些系统在没有实施单点登录的情况下会出现以下问题:
用户体验方面: 每天开始工作时,员工需要分别登录每一个系统才能正常开展工作,这不仅耗时,而且容易造成密码疲劳,即频繁记忆和输入不同系统的登录凭证,降低了工作效率。举例:员工小王每天上班要先登录内部邮箱查看重要通知,然后切换至项目管理系统更新进度,接着进入人力资源信息系统查看工资单。如果没有 SSO,他需要在每个系统单独输入用户名和密码。
安全管理方面: 各个系统间的密码策略可能不一致,员工可能会因为难以记忆而在多个系统使用同一密码,增加了数据泄露的风险。同时,管理员对用户账户的管理、权限变更及审计也会变得复杂。举例:若小王在每个系统使用相同密码,一旦某一系统存在安全隐患导致密码泄露,攻击者就有可能借此尝试登录其他系统。而有了 SSO,管理员只需在一处更改或撤销小王的登录权限,就能影响所有相关系统。
采用单点登录后,小王只需在一天开始时登录一次,之后访问其他所有系统时都将自动识别其身份并授权访问,无需再次验证。这样既减少了用户登录负担,又提高了安全性,因为管理员可以通过统一的入口更有效地执行身份验证、授权以及审计策略。同时,SSO 还可以配合多因素认证(MFA)等增强措施,进一步提升整个系统的安全级别。
1.单点登录实现原理
单点登录是在用户登录一个业务系统时,先将登录信息发送至单独的 SSO 服务器进行认证,如果认证成功则向该应用程序或系统发送授权令牌,之后该用户就可以使用授权令牌完成登录并操作所有系统了。
单独登录通常的操作流程是这样的:
用户认证:
- 用户首先访问一个系统,输入用户名和密码进行登录。
- 登录请求被发送到专门的认证中心(Authentication Server)。
- 认证中心验证用户的身份信息,如果验证成功,则生成一个安全令牌(如 JWT、Ticket 等)。
令牌发放与传递:
-
认证中心将令牌返回给用户首次登录的应用系统。
-
应用系统将令牌存储在用户的本地会话(如浏览器的 Cookie)中。
- 当用户访问其他需要 SSO 支持的应用系统时,浏览器会携带令牌自动发送给目标系统。
令牌验证与授权:
-
目标系统接收到请求后,发现携带了令牌,则将令牌发送给认证中心进行验证。
-
认证中心验证令牌的有效性(包括签名、有效期等)。
- 如果令牌有效,认证中心会返回一个确认信息给目标系统,证明用户已通过认证。
资源共享与授权:
-
目标系统接收到认证中心的确认后,允许用户访问系统资源,而无需再次登录。
- 目标系统可以依据令牌中的信息进行权限控制和角色映射。
会话管理:
-
为了保证安全性,一般会设置令牌的有效期,过了有效期后需要重新认证。
-
在某些实现中,当用户在一个子系统中注销时,会通知认证中心撤销所有关联令牌,从而实现全局注销,保证了其他系统也无法继续使用过期的认证信息。
在技术实现上,单点登录可以借助如 CAS(Central Authentication Service)、OAuth、OpenID Connect 等标准协议,也可以基于企业内部的自定义协议实现。在整个流程中,关键是要维护一个全局认可的信任票证(token),并通过集中式的认证服务中心来进行身份的统一管理和验证。
2.单点登录实现
在 Java 项目中,实现单点登录(SSO)的方案主要有以下几种:
OAuth2 + JWT(JSON Web Tokens)方案:OAuth2 是一个开放标准,允许用户授权第三方应用访问他们在服务提供商处存储的特定信息,而不需要将用户名和密码提供给第三方应用。JWT 是一种用于身份验证和授权的令牌,通常与 OAuth2 一起使用。在 Spring Boot 中,你可以使用 Spring Security OAuth2 和 JWT 库来实现这种方案。
CAS(Central Authentication Service)单点登录方案:CAS 是一个开源的、用于企业级的单点登录解决方案。它提供了一套服务端和客户端的组件,使得在多个应用之间实现单点登录变得简单。在 Spring Boot 中,你可以使用 Spring Security CAS 客户端来实现这种方案。
Spring Security + OAuth2:Spring Security 是一个提供身份验证和授权功能的框架,它可以与 OAuth2 一起使用来实现单点登录。在这种方案中,你可以使用 Spring Security 来处理用户的身份验证和授权,然后使用 OAuth2 来管理用户在多个应用之间的访问。
Spring Session:Spring Session 是一个用于管理用户会话的框架,它可以帮助你在多个应用之间共享会话信息,从而实现单点登录。你可以使用 Spring Session 来将会话信息存储在共享的地方(如 Redis),然后在每个应用中通过 Spring Session 来访问这些会话信息。
其中,OAuth2 + JWT 方案适合于需要对外提供 API 接口的应用,而 CAS 方案则更适合于内部系统之间的单点登录。Spring Security + OAuth2 方案则是一种比较通用的选择,既可以处理内部系统的单点登录,也可以处理对外提供 API 接口的情况。Spring Session 方案则更适合于需要将会话信息共享到多个应用之间的场景,它也是最早和最简单的单点登录实现方式。
3.SSO 和 OAuth2 有什么区别?
SSO 和 OAuth2 都是用于管理用户身份验证和授权的协议,但它们的目标和应用场景有所不同,具体区别如下:
目标:
- SSO 的主要目标是简化用户在多个应用系统中的登录流程,让用户只需要登录一次就可以访问所有授权的应用系统,提高用户体验和效率。
- OAuth2 的主要目标是允许第三方应用代表用户获得访问特定资源的权限,同时保护用户的敏感信息(如密码)不被泄露。
应用场景:
- SSO 通常用于大型企业内部或相关联的系统之间,用户只需要在一个地方(如企业门户)进行登录,就可以访问多个内部系统。
- OAuth2 广泛应用于第三方应用需要访问用户存储在服务提供商(如 Google、Facebook)中的资源时,用户授权第三方应用访问其资源,而无需将用户名和密码直接提供给第三方应用。
实现方式:
- SSO 的实现通常依赖于一个集中的认证中心(Authentication Server),用户在这个中心进行登录,并获得一个全局会话或令牌(Token),然后在访问其他应用系统时,这个令牌会被用来验证用户的身份和权限。
- OAuth2 的实现涉及四个角色:资源所有者(Resource Owner)、授权服务器(Authorization Server)、客户端(Client)和资源服务器(Resource Server)。用户(资源所有者)授权客户端访问其资源,授权服务器颁发访问令牌给客户端,客户端使用这个令牌访问资源服务器上的资源。
PS:SSO 和 OAuth2 都是用于管理用户身份验证和授权的协议,但 SSO 更注重于简化用户在多个应用系统中的登录流程,而 OAuth2更 注重于保护用户的敏感信息,并允许第三方应用代表用户访问特定资源。在实际应用中,它们可以相互结合使用,例如使用 OAuth2 来实现 SSO 中的令牌颁发和验证过程。
课后思考
说说 OAuth2 的实现原理?它有几种授权模式?OAuth2 常用框架有哪些?它们有什么区别?