SAML和OAuth2这两种SSO协议的区别

SAML和OAuth2这两种SSO协议的区别,第1张

SSO是单点登录的简称,常用的SSO的协议有两种,分别是SAML和OAuth2。本文将会介绍两种协议的不同之处,从而让读者对这两种协议有更加深入的理解。

SAML的全称是Security Assertion Markup Language, 是由OASIS制定的一套基于XML格式的开放标准,用在身份提供者(IdP)和服务提供者 (SP)之间交换身份验证和授权数据。

SAML的一个非常重要的应用就是基于Web的单点登录(SSO)。

在SAML协议中定义了三个角色,分别是principal:代表主体通常表示人类用户。identity provider (IdP)身份提供者和service provider (SP)服务提供者。

IdP的作用就是进行身份认证,并且将用户的认证信息和授权信息传递给服务提供者。

SP的作用就是进行用户认证信息的验证,并且授权用户访问指定的资源信息。

接下来,我们通过一个用SAML进行SSO认证的流程图,来分析一下SAML是怎么工作的。

上图中User Agent就是web浏览器,我们看一下如果用户想请求Service Provider的资源的时候,SAML协议是怎么处理的。

SP将会对该资源进行相应的安全检查,如果发现已经有一个有效的安全上下文的话,SP将会跳过2-7步,直接进入第8步。

RelayState是SP维护的一个状态信息,主要用来防止CSRF攻击。

其中这个SAMLRequest是用Base64编码的<samlp:AuthnRequest>,下面是一个samlp:AuthnRequest的例子:

为了安全起见,SAMLRequest还可以使用SP提供的签名key来进行签名。

IdP收到这个AuthnRequest请求之后,将会进行安全验证,如果是合法的AuthnRequest,那么将会展示登录界面。

这个form中包含了SAMLResponse信息,SAMLResponse中包含了用户相关的信息。

同样的SAMLResponse也是使用Base64进行编码过的<samlp:Response>。

我们可以看到samlp:Response中包含有saml:Assertion信息。

我们可以看到上面的所有的信息交换都是由前端浏览器来完成的,在SP和IdP之间不存在直接的通信。

这种全部由前端来完成信息交换的方式好处就是协议流非常简单,所有的消息都是简单的GET或者POST请求。

如果为了提高安全性,也可以使用引用消息。也就是说IdP返回的不是直接的SAML assertion,而是一个SAML assertion的引用。SP收到这个引用之后,可以从后台再去查询真实的SAML assertion,从而提高了安全性。

SAML协议是2005年制定的,在制定协议的时候基本上是针对于web应用程序来说的,但是那时候的web应用程序还是比较简单的,更别提对App的支持。

SAML需要通过>

认证 ( authenticate )和 授权 ( authorize )是两个容易被弄混的概念,尤其是只看英文。

由此可见,应用需要先认证用户身份,然后依据用户身份再授权,二者需要联合使用。

对于QQ或者微信这样的应用,用户在登录后会得到该账户的身份凭证。如果其他第三方应用信任并接受QQ或者微信的身份凭证,就可以直接使用该凭证通过第三方的 认证 而登录。登陆之后用户能有权限去做什么,这就是第三方应用根据自己政策而进行的 授权 。我们常遇到有网站在第一次使用QQ或微信账户登录之后需要绑定已用账户,就是因为虽然网站能够通过QQ账户的身份认证,但是对于这样的账户没有对应的授权。

同理,对于一个面向公司内部的服务环境,该公司可能有邮箱系统、网上办公系统、财务系统等等。如果这些系统都是独立的,那么公司的员工就需要每一个系统都分配一个账户,每个系统都需要单独登录。这样显然是低效而麻烦的,更好的解决方案应该是用户在内网中只需要登录一次,所有的子应用系统都能认证其身份,而免去重复登录,这样的方案就被称为单点登录( single sign-on, SSO )。

这样做的最明显的好处就是提高用户体验,用户只需要维护一对用户名和口令可以在公司内部畅通无阻。同时,因为是单点登录,所有的用户身份的都被 统一认证 ,也就是说用户的身份凭据(比如口令)只被保存在一处,其他子系统并不直接获得用户的口令等敏感信息,而是接收来自可信来源的身份z明。

单点登录和统一认证中主要的三个协议是 OpenID , OAuth , 金和 SAML ,被称为单点登录的三驾马车。这些协议已经有了各种语言版本的实现,本人也在其他文字做了详尽的介绍,这里专门对比下三种协议的异同。

OpenID是一种 认证 标准,互联网上有很多账户都是支持OpenID比如谷歌、雅虎、PayPal等等。

用户要使用OpenID就必须先在OpenID身份服务器(Identity Provider, IDP)获得OpenID 账号(比如Google账户)。用户可以使用OpenID账户来登录任何一个接受OpenID认证的服务应用(the relying party,RP,依赖方)。OpenID协议标准就是提供一个框架用来IDP和RP之间通信。

本质而言,用户的OpenID是一个为用户个人所拥有的特殊URL(比如 alice2016openidcom),所以有些网站甚至会提供选项让用户自己去填写OpenID。

FaceBook曾经也是使用过OpenID的,后来转而开发FaceBook Connect

OpenID的最新版本是OpenID Connect。具体协议信息请见这里 OpenID Connect 协议入门指南

准确来讲,OAuth2是一个授权的标准协议。也许会令人困惑,OAuth2是OpenID-Connect的基础,但是OpenID-Connect是认证协议(在OpenID-Connect中,ID-Token也被当做是一种资源)。

让我们回到OAuth2,OAuth2提供了一种代理访问机制,也就是说一个应用(可以被称为客户端)可以代替用户到资源服务器上获得属于用户的资源或是进行符合用户权限的 *** 作 ,而用户不用将自己的用户名和口令等身份凭据分享给客户端。OAuth2是通过IDP给第三方应用颁发令牌(Token)来实现以上功能的,第三方应用通过使用令牌向资源服务换取对应的资源。

在Twitter的OAuth指导手册中说OAuth2是一种认证协议,实际上,这是基于授权的“伪认证”。

OAuth协议的认证过程可以类比为如下流程:Alice要外出一段时间,让自己的朋友Bob代为照顾她的房子,所以Alice把自己房子的钥匙交给了Bob,而Bob也就可以任意的进入房子。这里的钥匙就是一种授权的体现——Alice授权Bob进入房子。在这里例子中,房子的所有者Alice就是用户,Bob是客户端,而门锁就是IDP,房子是资源服务器。

如果假设房子钥匙的拥有者就是房子的所有者,那么这个授权的过程也是一种 伪认证 ,之所以加一个伪字,是因为
这个假设并不是总是成立的,比如Bob虽然有钥匙,但是并不是房子的所有者Alice。

更多OAuth的内容,请参见我之前的文章。 OAuth20 协议入门指南

SAML协议是三者中时间最长的协议,最初版本制定于2001年,并于2005年修改。作为一种安全性断言标记语言,SAML协议既可以用于认证也用于授权。

所谓的安全性断言,就是关于认证、授权以及用户属性(比如用用户的有效或者住址等信息)的声明集合,在SAML中,这些断言以XML的格式传输。

当要验证一个用户身份时,服务提供商(Service Provider, SP,即RP,应有依赖方)会向IDP发出SAML认证请求,该请求中会以XML格式说明认证方式的设置,比如希望IDP以何种方式验证用户;IDP在认证通过用户身份之后,会返回SAML请求响应,同样以XML格式返回断言表明用户身份和相关属性,此外SAML安全性断言信息必须要使用数字签名以保证其完整性和不可抵赖性(没有强制要求对SAML断言加密);SP接收到SAML断言之后,验证其消息来源是否费受信任的IDP,验证通过之后解析XML获得认证信息。

除了断言,SAML还定义了如下概念:

更为详细的内容请见:

以下是三种协议的相关对比和总结,便于读者根据自己实际情形来选择下一步要继续去了解哪一种协议。

如果想进一步以上协议的具体,欢迎阅读我的其他文章:

由于网站的用户规模小,一开始没有自建用户体系,使用的是国内流行的几个开放平台的第三方帐号登录。比如:新浪微博、QQ、淘宝、人人网。

这些网站使用的都是OAuth 20协议实现的认证和授权,下面是我按照自己理解画的OAuth 20认证和授权流程图:
整个流程设计3个角色:用户,或者称浏览器;应用服务器,也就是用户访问的站点;开放平台(微博、QQ等)。这里以Weibo为例详细讲讲各个步骤:

用户点击网站页面上的“登录”按钮:

网站收到用户请求后,向开放平台请求一个Authorization Code。网站发送的这个请求url中会包含开放平台分配的APP KEY和一个回调地址。回调地址的作用是用户授权后开放平台通过该回调地址将access token返回给应用服务器。

浏览器页面跳转到开放平台的登录页面,要求用户登录。可以注意到这时浏览器地址栏中的地址是开放平台的域名,而非用户访问的站点,因此不必当心应用站点知道你的开放平台用户名密码。
用户输入用户名、密码,点击“登录”

用户在开放平台登录成功后,如果用户之前没有对当前访问的站点授权,或者已经取消了授权,那么开放平台会将页面跳转到授权确认页面:
默认都是最普通的权限。如果网站想要更高级的权限,需要将权限对应的编码作为scope参数添加到2中的url中。

用户根据网站需要的权限内容选择授权或拒绝。不管用户有没有授权,其实到了这一步都已经完成了2A中的Authentication即认证这一步了。只是如果用户没有对网站授权的话,网站就无法获取到用户的数据,无法进一步为用户提供相关服务。

用户授权以后,开放平台会生成一个Authorization Code,并通过网站提供的回调地址将该code发送给网站。

网站在拿到授权码(Authorization Code)后,就可以使用授权码到开放站点换取Access Token了。Authorization Code只表示得到了用户授权,具体访问用户资源还需要Access Token。

开放站点将Access Token返回给应用服务器。

网站使用Access Token请求用户基本信息。这里由于各个开放平台的api不一样,有时候可能需要不止一次请求,但逻辑上已经没有多大区别了。一旦网站有了这个Access Token,就可以调用开放平台提供的接口请求授权的用户资源。

Access Token有一个有效时间,通常是24小时。在这段时间内,如果用户不做修改密码或取消授权等动作,网站都可以使用该token获取用户的资源。

开放平台校验Access Token无误后,将当前用户的基本信息返回给站点。通常这段信息中会包括用户的昵称、性别、头像等。

站点获取到用户信息后,将页面跳转到登录成功页面,并使用获取到的信息为用户提供一个友好的页面提示,也可以利用该信息为用户提供更多的个性化服务。

背景

首先token认证方式的出现是伴随着系统架构的发展而来的。

最初的单机应用使用sessionId+cookie完全可以满足问题。

随着系统业务访问量加大,为满足服务高可用需求,系统引入了分布式架构,但是session只能存在单机节点上,为了解决这一问题,首先使用过 session粘贴 技术(通过hash等手段让请求始终访问之前生成sessionId的节点),这个方案的问题是万一存sessionId的节点挂了,整个系统都不能登陆了,也违背了高可用的设计思路;后来使用 session复制 的方案,即每台节点都copy一份sessionId,这引出2个问题,第一个就是分布式一致性的问题,节点同一时间重复创建了怎么办?另一个就是更头疼的系统扩展问题,随着系统越来越庞大,节点增多,session复制消耗的性能也越来越大,整个系统因为session出现了可遇见的性能瓶颈;再后来出现了session集中存储到一个地方,这样解放了服务器,但是session存储的高可用问题又来了,简直就是套娃式困局。

既然 有状态服务 出现瓶颈,大佬们开始提出 无状态服务 ,就是使用token验证方式替代较重的session,token就是一个字符串,只要服务根据约定好的算法解析出的结果跟预期一致就可以通过验证,也不需要保存在内存中,无状态服务的好处是系统扩展轻松,新追加的服务轻装上阵,完全没有顾虑。Oauth就是一种规范,用来保证token机制的可行,目前在web端和移动端都是主流登陆验证方案,Oauth20于2010年正式提出,一直沿用到现在,可见其稳定。

随着互联网行业迅猛发展,各种app,各种网站层出不穷,传统登陆方式就要求用户在每个想登陆的站点都要注册自己的账号信息和密码,这也留下了一定隐患,有的小站点可能技术不那么强,这就有可能导致用户信息泄漏,Oauth正好可以解决这种对一些站点即想用又不信任问题。从使用体验的角度,单点登陆的方式也可以简化用户对账号密码的管理。

Oauth2认证模式的4种类型

这种模式最常用,也是最安全的模式,相关的角色有3个:
客户端 (web站点/app,从认证服务的视角,不管你是web页面还是后台服务,都属于客户端范畴)、 资源服务 (存放个人信息的服务,比如微信存放你个人信息的服务)、 认证服务 (某可信的账户平台如微信平台)

使用之前需要在认证服务注册下自己的app信息(主要包括app名称、app站点、认证callback地址等),认证平台会给客户端创建一个clientId(客户端id)和client_secret(客户端秘钥)。这是为了解决认证平台不信任客户端的问题。

使用的时候用户首先会点击客户端登陆页上的一个链接,打开认证服务上的一个登陆确认页面,用户认证的时候会上传以下请求参数:

认证成功后,认证服务会重定向到redirect_uri,
同时认证服务还会按照之前注册好的callback地址,向客户端发一个get请求,参数:

这样客户端拿到了code,会再向认证平台的授权服务器发起请求,参数:

授权服务验证code没问题后,会给客户端返回token。

客户端拿着token就可以去资源服务器请求用户信息了(头像、姓名等)。

这种模式大致流程是:

这个模式不经过code验证的过程,这种token可以直接在callback的uri上看到,并且客户端后台也不会验证token,这种模式安全性显然没有授权码模式好,应用也不多。

流程:
用户直接在客户端上输入账号密码,然后由客户端向认证服务请求要token。

要使用这种模式就表明用户完全信任客户端了,如果信任客户端,直接在客户端上注册账号不就好了,何必把其他平台的账号告诉客户端,万一客户端保存了这个账号密码呢?

流程:
用客户端自己的名义向认证服务获取token,跟用户没什么关系。这也不会是登陆会考虑的场景吧

>我们假设有一个“云笔记”产品,并提供了“云笔记服务”和“云相册服务”,此时用户需要在不同的设备 (Android、iPhone、TV、Watch)上去访问这些“资源”(笔记、)

那么用户如何才能访问属于自己的那部分资源呢?此时传统的做法就是提供自己的账号和密码给我们的“云笔记”,登录成功后就可以获取资源了。但是这样做法会有以下几个问题:

为了解决上面的问题, OAuth应运而生。

OAuth 在“客户端”与“服务提供商”之间,设置一个授权层(Authorization layer)。“客户端”不能直接登录“服务提供商”,只能登录授权层,以此将用户与客户端区分开来。“客户端” 登录授权层所用的令牌(token),与用户的密不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。“客户端”登录授权层以后,“服务提供商” 根据令牌的权限范围和有效期,想“客户端” 开发用户存储的资源。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zz/13463055.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-08-12
下一篇 2023-08-12

发表评论

登录后才能评论

评论列表(0条)

保存