本文最初发布于devever.net网站,经原作者授权由InfoQ中文站翻译并分享。
现在,身份验证协议的数量快赶上应用程序协议,结果,这个领域很容易让人困惑。
最容易把人搞糊涂的是,很少有人注意到这样一种事实:
存在许多不同种类的身份验证协议,它们还试图扮演完全不同的角色。
与往常一样,首先请记住,身份验证和授权是不一样的功能。考虑到这一点,本质上存在三种不同的身份验证协议类别:
客户端到应用程序的身份验证协议由客户端发送给应用程序服务器进行身份验证。这种协议完全不揭示应用程序服务器在幕后如何使用客户端提供的信息对其进行身份验证。
应用程序到验证服务器的协议被应用程序服务器用来将客户端的身份验证委托给某个服务器,该客户端已使用客户端到应用程序的协议提供了信息,而验证服务器可以更好地执行身份验证决策。这种协议允许将身份验证处理外包给专门的身份验证服务器,并且无需让身份验证数据库对所有应用程序服务器都开放访问权限。
客户端的身份验证状态(例如通过客户端到应用程序的协议)通过单点登录服务器验证后,一台服务器使用单点登录协议与另一台服务器通信。换句话说,它们被用来传递身份验证决策。客户端先前成功通过验证服务器的身份验证的事实,可以在该客户端和应用程序服务器之间安全地传输。某些协议不需要进一步干预或需要单点登录服务器可用,即可允许客户端在初始登录后对应用程序进行身份验证,而其他协议则需要。
单点登录协议实际上包含两个协议:“客户端到验证服务器”部分和“客户端到应用程序”部分。客户端到验证服务器部分可能是定制的,有时可能是非常普通的客户端到应用程序的身份验证协议。而客户端到应用程序部分必须取决于SSO协议的设计。
在客户端到应用程序验证协议的范畴内,存在验证框架和验证方法。验证框架是一种可扩展的框架,它允许实施任意多种验证方法,并允许它在客户端和应用程序服务器之间动态协商使用哪种验证方法。
一些身份验证框架已集成到特定的应用程序协议中。还有一些通用设计旨在被集成到任意多个应用协议中。这样甚至将来出现的应用程序协议也可以利用框架中已经定义的所有身份验证方法,以及这些方法的库实现。
这类框架中可能最流行的是IETF的SASL。SASL没有定义特定的有线编码(这部分由应用程序负责),而是从本质上定义了身份验证方法名称(例如PLAIN、LOGIN、MD5等)的名称空间,以及协商它们的过程。实际的方法特定协议已经执行,但是应用程序协议仅需要促成不透明二进制字符串序列的来回交换,直到身份验证成功或失败为止。
简而言之,实现SASL的应用程序协议仅需要提供以下机制:
如何提供这些机制取决于应用程序协议,该协议必须定义一些适当的有线协议。尽管特定的编组和状态机是特定于应用程序协议的,但是SASL方法本身就足够独立于应用程序协议,因此实现各种SASL方法的通用SASL库被广泛采用。
一些最受欢迎的SASL方法是:
如今,人们通常会使用SASL方法(例如PLAIN或LOGIN),这些方法通过安全通道(例如TLS)以明文形式传输密码。
HTTP定义自己的身份验证框架,并具有自己的方法集。可以说,HTTP避免SASL的原因在于其无状态性和SASL不太相称。由于HTTP设计的运行机制是让客户端发送单个请求块,然后由服务器发送单个响应,因此HTTP协议不适用于SASL设想的身份验证完成之前的来回数据交换。
此外,对于每个请求都必须重复这种交换。
服务器通过发送一个401 Authorization Required错误,和WWW-Authenticate标头来请求身份验证以访问资源。该标头包含:
一些常见的HTTP身份验证方法有:
SSH还使用一组可扩展的方法定义了自己的身份验证框架。最常用的方法有:
客户端到应用程序的身份验证方法通常可以分为几个基本的类别:
如今这些策略都已经过时了,首先是由于人们常结合使用TLS与纯文本传输,其次是因为它们倾向于避免以哈希形式在服务器上存储密码,或者要求以与验证方案相关的特定方式对密码进行哈希处理。这样的话,密码哈希方法就会和身份验证方法高度耦合。
另一类身份验证协议与客户端到应用程序的身份验证协议完全无关,而是应用程序到身份验证服务器的协议,或称后端协议。后端验证协议是在应用程序服务器和验证服务器之间使用的(而不是在要验证的实体和对其进行验证的实体之间做一个协议),以便验证客户端提供的验证细节。
这些协议经常用于网络访问场景中,其中“应用程序”服务器是网络设备,如路由器、交换机或Wi-Fi接入点。由于我们不希望网络中的每个Wi-Fi接入点都保留身份验证数据库的副本,因此后端协议允许将身份验证决策外包给一个中心化授权源。因此,后端协议必须与某种客户端到应用程序的身份验证协议结合使用:在客户端和应用程序之间使用客户端到应用程序协议,在应用程序和身份验证服务器之间使用后端协议。
流行的后端身份验证协议包括RADIUS及其后继者DIAMETER,它们主要用于网络访问场景(例如拨号Internet身份验证、Wi-Fi身份验证等)。由于这些协议原本设计用于支持网络访问场景,它们都属于“AAA”(同时支持身份验证、授权、计费)协议。例如,如果需要,它们的计费功能可对拨号Internet连接进行基于时间和使用量的准确计费。
尽管LDAP不是为后端身份验证协议设计的,但它有时也被当成身份验证协议来用。应用程序服务器可以尝试向LDAP服务器进行身份验证来验证用户凭据。这种方法还有一个优点是,如果成功,则应用程序服务器还可以使用LDAP检索有关用户的信息。
RADIUS和DIAMETER这样用于网络访问场景的后端验证协议,传统上设计用于和特定的客户端到应用程序验证协议结合使用,比如由PPP定义的那些。PPP是一个OSI第2层协议,支持通过串行线路和拨号调制解调器发起IP网络连接。PPP定义了自己的可扩展身份验证框架,并支持以下方法:
EAP本身是一个身份验证框架,定义了一组可扩展的身份验证方法,这意味着与PPP一起使用时,方法协商分为两个级别:首先要协商EAP,然后必须协商一个特定的EAP方法。人们认为EAP与其他PPP身份验证协议不同,前者设计同时用于PPP和其他网络访问上下文(例如Wi-Fi身份验证或以太网802.1x身份验证)。(802.1x是对以太网的扩展,可以根据成功的EAP身份验证来确定网络访问权限)。
EAP和SASL之间有一些相似之处,因为它们都是支持可扩展方法集的通用框架。但是,EAP定义了一个特定的有线协议,而SASL没有定义。此外,EAP旨在支持网络访问应用程序,而SASL旨在支持应用程序级别的身份验证应用程序。
但是,关于EAP的最重要的一点是,它从一开始就被设计为可被应用程序服务器不透明地经隧道传输。例如,假设你通过调制解调器拨入路由器,并建立PPP连接。路由器必须了解协议(例如PAP或CHAP),并且知道如何通过RADIUS或DIAMETER与后端服务器交互协议。
在现代应用程序中,例如Wi-Fi客户端对一个WLAN接入点发送EAP,接入点只会将EAP消息作为不透明数据,然后将其在RADIUS或DIAMETER会话中通过隧道传输到一个网络身份验证服务器上,让网络身份验证服务器来处理EAP消息。身份验证服务器同样可以返回封装在RADIUS或DIAMETER会话中的EAP消息,Wi-Fi接入点将其解包并传递给客户端。这样,网络设备就与所使用的身份验证方法无关,并且不需要升级就能支持新的身份验证方法。只有验证服务器和客户端需要升级。
请注意,客户端永远不会发送RADIUS或DIAMETER。RADIUS和DIAMETER是严格的后端协议。因为EAP消息始终在转发到身份验证服务器之前被封装在RADIUS或DIAMETER消息中(身份验证客户端无法控制的进程),所以RADIUS或DIAMETER消息可以包括与EAP无关的,身份验证服务器感兴趣的客户端信息消息本身。例如,如果客户端正在为启用802.1x的以太网端口发起验证,则交换机可以包含关于客户端连接到哪个端口的信息,并且身份验证服务器可以预见它在这上面的决策。
现在,我们讨论最复杂,最有趣的身份验证协议:单点登录协议。如前所述,单点登录协议必须包括两个部分:用于验证客户端到验证服务器的协议,以及用于验证客户端到任意应用程序服务器的协议。前者可能是标准的客户端到应用程序协议,也可能是定制的协议。而SSO协议的性质要求后者是SSO协议所特有的,并且是任何SSO协议的核心。
SSO协议可以大致分为Web和非Web SSO协议。最受欢迎的非Web SSO协议是Kerberos。
Kerberos允许客户端使用定制的身份验证协议向身份验证服务器发起身份验证;客户端会收到一个票证,该票证能以密码方式向应用程序服务器发起身份验证,而无需与Kerberos身份验证服务器之间进一步的通信(验证服务器在用户登录后可能会关闭,并且不会立即让所有应用程序无法访问)。
该协议还支持客户端来验证服务器,以及服务器来验证客户端。如今,*nix和Windows Active Directory环境都使用Kerberos。对于客户端到应用程序的身份验证,通常不直接在身份验证框架内将其实现为身份验证方法。
相反,它通常是通过GSSAPI调用的,并且是主要的用法,例如SASL GSSAPI方法、HTTP Negotiate(GSSAPI)身份验证方法和SSH GSSAPI身份验证方法。
有趣的是,Kerberos的当前版本Kerberos 5于1993年发布,因此仅依赖对称加密,避免了对非对称加密的依赖。如果Kerberos是今天设计的,则它可能会使用公钥加密,并且对中心化身份验证服务器的依赖会稍少一些。
不幸的是,Web的极速增长看来已经侵蚀了所有非web协议(无论是身份验证还是其他用途)的发展空间。(但Kerberos 5仍然是安全的。)
对于Web SSO协议,客户端到身份验证服务器协议一直是标准的Web形式,也就是表单-cookies形式。客户端到应用程序服务器的身份验证协议却很特殊。
通常,当应用程序服务器希望对客户端进行身份验证时,它将通过HTTP重定向将客户端引向SSO身份验证服务器。如果客户端尚未通过中心化验证,则会要求它进行验证;否则,如果客户端已经完成单点登录,则流程将继续进行而无需用户干预。
在对用户完成身份验证之后,身份验证服务器会通过另一个HTTP重定向将客户端引回到应用程序服务器。返回请求包含从身份验证服务器传输到应用程序服务器的身份验证信息,以建立客户端的凭据。该数据本身将以某种方式进行身份验证,以防止客户端对其修改。由于信息从身份验证服务器到应用程序服务器的传递是通过客户端进行的,因此客户端就像是携带花粉的蜜蜂。在某些SSO实现中,应用程序服务器可以直接回调身份验证服务器,以验证它已通过客户端接收到的信息。在其他SSO实现中,通过客户端从身份验证服务器传递到应用程序服务器的信息是加密保护的,不需要进一步验证。
应当注意,上文不是对特定SSO协议的描述,而是对所有常用技术的概括。由于Web应用程序仅需要符合标准的Web浏览器,因此对在Web平台之上实现的协议进行标准化的要求较少,于是出现了许多专有的Web SSO实现。
但一些标准还是出现了。今天流行的标准有:
曾经被广泛采用,但现在已经过时的协议包括:
最后我们讨论一些系统本地身份验证API。这些不是协议,但与协议关系很近。
PAM(可插入身份验证模块)是nix领域中本地身份验证的事实标准。它在linux上普遍用于本地身份验证,并且在其他nix操作系统上也很流行。PAM提供了基于插件的身份验证功能;PAM插件是动态链接库,可以在运行时加载以提供任意身份验证逻辑。使用何种PAM插件由系统配置确定,因此可以根据需要重新配置PAM。
尽管PAM具有高度可扩展性,但它被设计为支持终端交互式登录应用程序,因此受到了限制。PAM模块向用户提交一系列零个或多个交互式提示(例如“Password:”),因此不能支持Kerberos那样的SSO身份验证方法(尽管有的PAM模块可以提示用户输入Kerberos密码并执行初始Kerberos登录)。
虽然PAM主要是为了支持终端交互式登录而设计的,但将PAM用作某些应用程序协议的后端(例如,用作SASL PLAIN的后端)也是可行且普遍的。但是,这要求应用程序服务器理解(或正确猜测)PAM模块发出的线路提示的语义。例如,Dovecot IMAP服务器假定,如果PAM模块要求输入没有字符回显的行,则说明它要求输入密码;如果该模块要求输入一行启用了字符回显的内容,则它是在要求用户名。因此,虽然PAM模块可以被编写为支持通过TOTP硬件密钥进行身份验证,并在终端上提示输入六位数的值,但非终端应用程序(例如SASL应用程序)无法支持它,除非专门设计为支持这种模块的提示。
GSSAPI是另一个本地API,具有正式标准。它设计用于网络应用程序(而不是终端交互),并且最常用于通过Kerberos SSO启用身份验证。实际上,尽管它是旨在扩展到任意身份验证方案的通用API,但它几乎只被用于Kerberos、SPNEGO和NTLM应用程序。可以通过SASL GSSAPI方法,通过任何SASL应用程序使用GSSAPI。
原文链接:
https://www.devever.net/~hl/auth