以下内容纯粹是出于对技术的好奇,将网络上搜索的材料结合自己的理解整理而来。由于没有实操经验,纯粹纸上谈兵,如有错误,欢迎斧正。
--------
部分内容于2023/2/2更新
单点登录(Single Sign-on, SSO)是当下WEB应用开发常用的身份认证方法。它使用集中式身份认证模式,允许用户使用相同的身份,在一个系统中通过认证,就可以访问其他相关但独立的系统/服务。每个系统不用自己去设计、实现用户的身份认证。常见的例子如google全家桶,当登录了Gmail之后,再去访问Youtube,就不需要再次手动输入登录信息即可使用服务。
与单点登录易混淆的概念是相同身份登录(Same Sign-on,SSO)。相同身份登录是使用轻量级目录访问协议(Lightweight Directory Access Protocol, LDAP)去访问身份服务器/数据库来进行身份认证。对于每个系统,都需要手动输入用户名、密码。
Web服务器对于已登录的用户进行认证有两种方法:
HTTP是无状态的协议。在某些应用场景,需要知道登录的用户的状态,于是就使用了会话(Session)的机制。用户的会话信息存储在应用服务器端,同时会将部分会话信息(如session ID,会话标识)存储在客户端浏览器的cookie中。在后续与服务器的通讯中,浏览器会携带相关信息,服务器通过查询存储的会话信息就能够取得用户的登录状态。
令牌,通常指JWT(JSON Web Tokens),以JSON格式存储的用户身份及相关信息,在服务器端通过密钥签名后使用base64编码成字符串。因为JWT是经过服务器签名的,客户端只能验证,不能更改。服务器在对用户进行认证后,会将令牌发送给客户端。客户端与服务器进行通信时,会在报文头中以Bearer authentication携带令牌,服务器收到后进行校验。不同于基于cookie的会话管理,令牌是无状态的,服务器本身不存储用户状态。令牌的自包含身份信息属性使得其应用更有弹性,易于扩展。
另一种令牌是由服务器生成的随机字符串,无实际意义。
借用auth0.com的一张图来描述单点登录是如何工作的。Auth0 SSO的核心思想是在认证服务器所在域建立用户的会话信息,所有的认证请求均由认证服务器完成。其实现方法是结合使用Session cookie和令牌。
图中的Auth Server,就是集中式身份认证服务器,也是实现单点登录的关键。需要使用SSO的应用需要在认证服务器进行注册。用户的身份信息可以存储在认证服务器,也可以在单独的身份服务器,认证服务器通过LDAP去访问获取。集中式身份认证服务器是共同信任的第三方,用户在通过它的认证后,相关系统通过查询认证状态,就能够实现单点登录。
假设domain1.com和domain2.com是两个相关但独立的WEB应用,使用相同的身份认证服务器进行了注册且均激活单点登录功能。
由于cookie中所保存会话标识的敏感性,服务器在设置cookie时会将其标识为“HttpOnly
”,这样可以防止该标识被读取后用于其他的脚本中。所有的客户端和服务器端的通信均应启用HTTPS,防止通信被窃听。
对基于浏览器的WEB应用,记录身份认证服务器所在域的会话是实现单点登录的关键。单点登录为用户访问多系统带来便利,这也对集中式的身份认证服务器提出了更高的要求。一旦服务器出现单点故障,将会使所有依赖单点登录功能的系统受到影响。因此,认证服务器需要有适当的冗余措施来保持高可用性。
目前已经有相当数量的单点登录实现方案,可以参考维基的这篇文章《List of single sign-on implementations》。
主体(Subject):是指提出访问请求的实体、动作的发起者,但不一定是动作的执行者。主体可以是某个人,某个进程。
客体(Object):是指可以接受主体访问的被动实体。凡是可以被操作的信息、资源、对象都可以被认为是客体。
认证(Authentication):确定主体是否就是其所声明的身份。
授权(Authorization):确定认证过的主体是否有权访问资源。
在最开始研究单点登录的过程时,关于认证、授权这块困扰了我许久。这涉及到主体、客体的确认问题。比如A访问B时,A是主体,而B是客体。当B响应A的请求再去访问C时,B就成了主体,C是客体。类似,在谈论认证、授权时,应明确哪个主体对客体的认证、授权。
以OAuth 2.0为例,用户的身份信息存储在认证服务器或者单独的身份服务器。OAuth是一个授权协议,为什么它能在单点登录中实现了认证的功能呢?
在domain1.com向认证服务器发起用户认证请求时,认证服务器会首先对domain1.com进行身份认证。认证方法取决于认证服务器的实现。认证通过后,认证服务器会检查用户的登录状态。假如用户之前没有在domain1.com注册过,用户通过认证服务器提供的登录页面登录并通过验证后,会出现一个页面让用户手动确认授予domain1.com获取自己的身份及相关信息的提示,即用户的明示同意。这是一个标准的授权行为,用户(身份信息的所有者)授予客户(domain1.com)读取自己相关信息的权力。
在后续的流程中,认证服务器通过验证domain1.com有权读取用户的信息,将签名的令牌返回给domain1.com,这是告知domain1.com用户已通过身份认证。
当用户登录domain1.com后访问其提供的资源时,这就变成了domain1.com对用户进行授权。这个授权可以由domain1.com根据自己的规则实现。