一、历史发展过程
1、单个web服务的登录
http的无状态
我们开发的web应用,用户用浏览器访问我们的服务器,交互使用的http协议,http协议本身就是无状态的。多次http请求之间没有任何关联。
会话机制
我们用http请求资源,服务端肯定是希望能标识出用户的信息,他是谁,有没有权限。这个信息就可以通过会话机制来存取。
浏览器请求到了服务器,服务器会创建一个会话,并且会将会话id作为响应的一部分发送给浏览器。浏览器把会话id存到cookie中。在后续的请求时带上这个cookie中的id,服务端就能知道是同一个用户了。
能这么作依赖于下面技术事实:
- cookie是浏览器用来存储少量数据的机制,以key/value形式存储,浏览器发送请求时自动附带cookie信息。
- 当我们用的tomat服务器,浏览器会被设置一个名为“JSESSIONID”的cookie,它维护的就是会话id。
登录状态
基于上面的会话机制,我们可以把用户的登录态存到会话中。当第一次用户请求登录网站,带上用户名密码,网站服务端校验通过后,将这个会话标记为“已登录”状态。后续的请求都能表明用户已登录。
HttpSession session = request.getSession();
session.setAttribute("isLogin", true);
如上,虽然http无状态,我们通过web的会话机制,是可以维持登录态的。
2、多个web服务的登录
随着系统数量的发展,如果用户要访问的不再是一个web系统,但是希望登录其中一个web系统后,其他系统也能作为已登录状态。
为了实现多个系统的登录,如果还是以来session会话机制,必须解决两个问题:
- Cookie是不能跨域的,如果Cookie的domain属性是sso.a.com,在发送给app.a.com的请求是带不上这个cookie的。
- 多个系统是不同的web应用,它们的session存在自己的应用内,是不共享的。
下面方案来解决上述问题:
- 多个web系统之间共享会话session。
- 多个站点的域名统一在一个顶级域名下,比如"*.baidu.com", 设置cookie的域为“baidu.com”.
上面方案有如下缺点:
- 应用群的域名必须统一的顶级域名
- 应用群各系统使用的技术(web服务器)要相同,不然cookie的key值(tomat为JSESSIONID)不同
- cookie本身不安全
因此,我们需要“单点登录”技术。
二、单点登录
2.1 token发送和使用的两种方式
在多个服务提供单点登录(SSO)的场景中,关于token的发放和使用,主要存在两种方式,这取决于具体的实现方案和系统架构。
(1) 使用统一的token
在Token-Based SSO的实现中,用户通常在认证服务器上进行一次身份认证,如果验证成功,认证服务器会颁发一个统一的Token给用户。这个Token会被发送到客户端(如浏览器或移动应用), 并在后续的请求中携带这个Token来访问其它服务。每个服务在接收到请求时,都会将Token发送到鉴权中心(或认证服务器)进行验证,以确认用户的身份和权限。
优点:
- 安全性高:Token本身可以通过加密和签名等手段来保证安全性,防止伪造和篡改。
- 易于管理:只需要管理一个统一的Token,简化了系统架构和管理工作。
- 支持跨域:不依赖于Cookie,因此可以很容易地处理跨域问题。
缺点:
- 性能压力:每次请求都需要去鉴权中心验证Token,可能会增加鉴权中心的性能压力。
- 单点故障:如果鉴权中心出现故障,可能会影响所有服务的正常运行。
(2) 服务各自发送token
另一种方式是,每个服务在用户验证通过后,自行给用户发放一个Token。这个Token只在该服务内部有效,用于后续的请求验证。这种方式下,用户可能持有多个Token,每个Token对应一个服务。
优点:
- 减轻鉴权中心压力:由于每个服务自行验证Token,因此减轻了鉴权中心的性能压力。
- 降低单点故障风险:即使某个服务出现故障,也不会影响其他服务的正常运行。
缺点:
- 管理复杂:需要管理多个Token,增加了系统的复杂性和管理成本。
- 安全性稍低:如果某个服务的Token验证机制存在漏洞,可能会影响该服务的安全性。
结论
在实际应用中,选择哪种方式取决于具体的需求和系统架构。如果系统对安全性有较高要求,且服务数量不多,可以考虑使用统一的Token。如果系统对性能有较高要求,或者服务数量较多,可以考虑服务各自发放Token的方式。
无论选择哪种方式,都需要确保Token的安全性,包括使用安全的加密算法和签名机制,以及定期更换Token等安全措施。同时,还需要考虑系统的可扩展性和可维护性,以便在需要时能够方便地添加新的服务或调整系统架构。
三、SAML2.0
SAML2.0 是一个开放标准,通常用于提供单一登录基于Web的应用程序,该协议用于身份验证和授权。
SAML协议具有三个实体,用户代理(通常是用户的Web浏览器)、服务提供商或SP(你尝试访问的应用程序)、身份提供商或IDP。
在配置SAML联合时,您在服务提供商和身份提供商之间建立信任关系。如果用户成功进行身份验证并获得授权,则想要访问服务提供商的用户必须首先通过IDP进行身份验证。当IDP对用户鉴权成功,IDP会创建“断言”,断言将发送到应用程序,并且由于应用程序信任IDP,因此允许用户访问并且由于用户已经通过IDP身份验证,因此用户可以单点登录到其他应用程序。
让我们更深入地了解以下SAML流程,身份提供商了解您的用户及其属性,您的服务提供商对用户有自己的了解。
当IDP创建一个断言时,它会使用用户标识符填充该断言并将其发送到SP。现在SP会验证该断言,但我们不能只以明文或完全不受保护的方式发送它,因此IDP必须首先签署断言, 这样SP可以验证断言的发布者,从而信任。
接下来SP读取用户标识符并尝试将其映射到它自己的用户存储,如果用户找不到,这种就是失败的情况。
联合工作的用户属性,我们需要建立一些集成规则,例如SP可能规定用户标识符和格式应该是电子邮件地址,然后IDP必须同意。当双方具有相同的配置时,并进行配置以匹配此配置SAML断言可以映射到服务提供商处的用户对象,从而服务提供商可以允许访问配置或集成规则,这对于成功建立SAML联合至关重要。
配置可以手动输入到您的SP或IDP中,但通常您将要求和功能收集到XML元数据文件中,该文件包含系统的设置和证书,现在您可以交换这些文件来配置联盟,该元数据交换就是建立的信任。元数据文件包含用户标识符的格式,称为名称ID格式,名称ID格式的名称是标准化的。
双方都已配置同样,元数据通常包含发送者的证书以及使用该证书,接收端可以验证断言的签名并知道它来自受信任方。
实体标识符也包含在文件中,这将唯一地标识我们的发送者或接收者,稍后我们将回到元数据,但首先让我们看一下用户如何启动身份验证流程。
参考:
单点登录原理与简单实现 - ywlaker - 博客园 (cnblogs.com)