1. 过于详细!终于搞懂SSO里面的SAML和OIDC讲的啥了
在了解SSO是什么之前,我们需要搞清楚两个概念: Authentication & Authorization。
Authentication(又被称为AuthN,身份验证),它指的是 the process of verifying that "you are who you say you are",也就是说这个过程是为了证明你是你。通常来说有这么几个方式:
Authorization(又被称为AuthZ,权限验证),他指的是 the process of verifying that "you are permitted to do what you are trying to do",也就是说这个过程是为了证明你是否拥有做这件事的权限,比如修改某个表格等等,如果没有权限的话通常会返回 403 错误码。
在 SSO 出现之前,用户在不同的系统登录就需要在不同的系统注册多个账号,然后需要自己记住多个用户名和密码,而如果这些系统是同一个平台的话,其实该平台还需要维护多套几乎一模一样的登录系统,给用户和平台都带来了负担。
而 SSO 就是一种authentication scheme(身份验证方案),SSO 允许用户使用同一个账户登录不同的系统,很好地解决了上述的问题。它不但可以实现单一平台的登录,假如某个平台之外的系统是信任该平台的,那么外部系统也可以集成这个平台的 SSO, 比如现在的大多数网站都提供了 Google 账号登录的功能。
要实现 SSO,首先需要你正在开发的系统信任这个第三方登录系统所提供的用户信息,然后你需要按照一定的标准和协议去与其对接,接下来我们会介绍两个比较常用的 SSO 协议 -- SAML 2.0 和 OIDC。
SAML 2.0是什么
SAML 是 Security Assertion Markup Language 的简称,是一种基于XML的开放标准协议,用于在身份提供者(Identity Provider简称IDP)和服务提老伏供商(Service Provider简称SP)之间交换认证和授权数据。
SAML 2.0是该协议的最新版本,于2005年被结构化信息标准组织(OASIS)批准实行。
流程
SAML flow
SAML Assertion
那么这个 SAML Assertion 又是个啥呢?
首先用户为什么可以访问SP上的资源呢?肯定是因为没含高其实SP也有一份用户的资料,这个资料里面可能有用户的账户信息,权限等等,但是现在用户的信息是由IDP提供的,所以现在需要做的就是讲两份用户信息映射起来,好让SP知道IDP提供的用户到底是哪一个。
而这个映射的约定,就是SP和IDP进行集成的时候的一个配置,这个配置叫做 metadata。这个配置有两份,两边各一份,里面约定了应该怎么去映射用户信息,签名的证书等。IDP和SP会通过别的方式去交换这两份 metadata。
所以其实 SAML Assertion 里面包含了用户的唯一标识,能够证明该用户是谁。在SP拿到这份信息后就会按照一些规则去验证里面的信息是否是合法的用户。
那么问题来了,如果中间人知道了我们之间的规则随便塞了一份信息进来咋办?所以其实 SAML Assertion 里面除了用户信息其实还有IDP的签名,只有SP先解析了里面的签名确认无误之后才会信任这份信息。
知道了 SAML Assertion 是个啥以后,我们还需要弄清楚它是怎么发送出去的。要弄清楚它们是怎么发送出去的我们需要知道一个东西叫做 binding method。
SAML 2.0 有许多不同的 binding,它们其实就是 SAML Assertion 的交互方式:
其中现在用的比较多的是前三种,它们都是基于HTTP协议来实现的。
metadata
上面提到过 metadata 是为了让IDP和SP明白彼此交流的信息,并且有一些枯尺安全考虑,里面主要的信息有:
其中有一个字段 md:KeyDescriptor 在SP中有一个 encryption,在SP和IDP进行通信建立信任的时候,IDP就会拿到SP加密的key,在用户登录成功后,IDP就会用这个key加密 SAML Assertion,SP拿到后通过自己的私钥进行解密。另一个叫 signing 的字段会被用来解析对方的签名,用来辨别这个 Assertion 是不是我想要的人发过来的。
OIDC是什么
OpenID Connect(OIDC) 是建立在 OAuth 2.0 协议之上的一个简单的身份层,它允许计算客户端根据授权服务器执行的认证,以 JSON 作为数据格式,验证终端用户的身份。它是 OpenID 的第三代规范,前面分别有 OpenID 和 OpenID 2.0。它在OAuth 2.0 的基础上增加了 ID Token 来解决第三方客户端标识用户身份认证的问题。
它的结构如图所示:
image-20200601085202978
从它的结构图中可以看出,除了核心实现外,OIDC 还提供了一系列可选的扩展功能。比如:
由于图片距今已经有些年限了,其实现在OIDC还提供了许多可选的扩展,具体可到官网查看。
流程
由于 OIDC 是基于 OAuth 2.0 的,所以 OIDC 也拥有多种 flow。由于篇幅所限我这里会相对详细地解释 Authorization Code Flow,在开始前我们需要弄清楚几个名称:
Authorization Code flow
Implicit Flow 是在 OP redirect EU 到 RP 的时候会带上 ID Token 和 Access Token(如果必要) 而不是 Authorization Code,同时在发送请求的时候也会有一些不同,需要带上一些别的参数,这里就不细讲了,总的流程是差不多的,详情可以查看这里
Hybrid Flow 可以理解为上面两个 flow 的结合,OP redirect EU 到 RP 的时候会带上 Authorization Code,同时根据发送请求时候 Response Type 参数的不同还会带上一些别的参数,具体流程可以参考这里
2. OAuth2.0和OIDC详解
OAuth 是一个开放标准的授权框架,它为第三方应用获取资源所有者在资源所在系统或应用上的部分资源提供了一种解决方案。
也就是说,假如你在腾讯云存了一些图片,现在你想在美图秀秀上编辑这些图片;此时的 "你" 就是资源所有者,第三方应用就是美图秀秀,而资源服务器就是腾讯云;
这种情况下美图秀秀直接访问腾讯云是获取不到你的图片的,所以美图秀秀为了能获取到这些照片就需要授权服务器授权(当然,资源服务器和授权服务器有可能是同一个,也有可能是两个不同的服务)
OAuth 就是为这种类似的场景定义的一套标准拆羡,目前已经发展到了 OAuth2.0 。 OAuth2.0 在 RFC 的文档地址: https://datatracker.ietf.org/doc/html/rfc6749
下面可以通过一个场景来解释一下, OAuth2.0 的原理:一个快递员的问题
假设你住在一个大型的小区中,你经常点外卖,而小区有门禁系统,进入的时候需要输密码
为了能让快递员进入,你就需要为他提供一组密码
如果你直接把你的密码给了快递员,那么他就有了和你一样的权限,如果你想取消他的权限,那只能改密码了,这样你还要通知使用该密码的其他人
所以你打算设计一套授权机制,既能让快递员进来,又能限制他的操作并且能随时回收这个密码
于是,你想出了一套办法,完善门禁系统:
此处为什么要给他生成一个令牌,而不是直接给他开门呢?
因为从小区大门到目的地可能会有多个门禁,所以就不用一直等着给快递员开门了;同样的,如果第二天快递员再来时就不需要再获取权限了
密码和令牌都让获取第三方获取用户数据,但是相较于密码,令牌有如下的有点:
令牌能够有效的控制第三方应用的访问权限和访问时长;当然,令牌也是必须要保乎御迅密的,因为泄露令牌和泄露密码一样,也会造成安全问题,因此一般令牌的有效时间都会设置的比较短
OAuth2.0 提供了四种授权方式来应对不同的应用场景,
授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
第一步,A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。
上面 URL 中, response_type 参数表示要求返回授权码( code ), client_id 参数让 B 知道是谁在请求, redirect_uri 参数是 B 接受或拒绝请求后的跳转网址, scope 参数表示要求的授权范围(这里是只读)。
第二步,用户跳转后,B 网站会要求用户登录(如果是未登录的情况下),然后询问是否同意给予 A 网站授权;如果用户同意授权,这时 B 网站就会跳回 redirect_uri 参数指定的网址。跳转时,会传回一个授权码,就像下面这样。
上面 URL 中, code 参数就是授权码。注:这个授权码与客户端一一对应,通常只有10分钟的有效期,并且只能使用一次
第三步,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。
上面 URL 中, client_id 参数和 client_secret 参数用来让 B 确认 A 的身份( client_secret 参数是保密的,因此只能在后端发请求), grant_type 参数的值是 AUTHORIZATION_CODE ,表示采用的授权方式是授权码, code 参数是上一步拿到的授权码, redirect_uri 参数是令牌颁发后的回调网址。
第四步,B 网站收到请求以后,就会颁发令牌。具体做法是向 redirect_uri 指定的网址,发送一段 JSON 数据。
上岁此面 JSON 数据中, access_token 字段就是令牌,A 网站在后端拿到了。
有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。 RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。
第一步,A 网站提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。
上面 URL 中, response_type 参数为 token ,表示要求直接返回令牌。
第二步,用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回 redirect_uri 参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。
上面 URL 中, token 参数就是令牌,A 网站因此直接在前端拿到令牌。
注意,令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。
如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。**
第一步,A 网站要求用户提供 B 网站的用户名和密码。拿到以后,A 就直接向 B 请求令牌。
上面 URL 中, grant_type 参数是授权方式,这里的 password 表示"密码式", username 和 password 是 B 的用户名和密码。
第二步,B 网站验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 因此拿到令牌。
这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。
最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。
第一步,A 应用在命令行向 B 发出请求。
上面 URL 中, grant_type 参数等于 client_credentials 表示采用凭证式, client_id 和 client_secret 用来让 B 确认 A 的身份。
第二步,B 网站验证通过以后,直接返回令牌。
这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。
A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。
此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个 Authorization 字段,令牌就放在这个字段里面。
上面命令中, ACCESS_TOKEN 就是拿到的令牌。
令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。
具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。
上面 URL 中, grant_type 参数为 refresh_token 表示要求更新令牌, client_id 参数和 client_secret 参数用于确认身份, refresh_token 参数就是用于更新令牌的令牌
OAuth2.0 描述了授权 (Authorization) 的各种方式,但是这些方式中却没有定义如何进行认证 (Authentication)
认证 (Authentication) 和授权 (Autherization 这两个表示的是不同的动作:
OpeID Connect (OIDC)对 OAuth2.0 进行了扩展,添加了用户认证的功能,并且它和 OAuth2.0 的流程是相同的。有区别的地方就是它的认证请求的字段中包含 scope=openid 如下所示:
在返回的响应中包含 ID Token ,用于获取用户身份,如下所示:
这里面有几个问题:
首先,
首先需要保证你的 OAuth2.0 请求是在 HTTPS 协议下发送的,这样可以防止暴露用户的信息。
其次就是一些钓鱼网站;比如,有一个 A 网站需要获取你在 B 网站上的资源或者数据,所以当你进入 A 网站的某个功能时,它会让你跳转到 B 网站,但是很有可能 B 网站是由 A 网站伪造跳转过来的,此时需要你的授权,当你输入账密的时候,你的账密就泄露了;这些钓鱼网站就是用来收集用户的账密信息的,所以当跳到第二个网站的时候一定要证实该网站是不是你注册过的合法的网站
参考连接:
https://datatracker.ietf.org/doc/html/rfc6749
https://auth0.com/intro-to-iam/what-is-oauth-2/
https://www.csoonline.com/article/3216404/what-is-oauth-how-the-open-authorization-framework-works.html
https://www.ruanyifeng.com/blog/2019/04/oauth_design.html
https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc
https://blog.runscope.com/posts/understanding-oauth-2-and-openid-connect
3. 谈谈单点登录
寒假学习的小课题,把之前的笔记整理整理记录一下(长文警告)因为当时看到的东西涉及很多,所以有一些地方没有深入去探讨。
网络:单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
简而言之就是用户在多个相互信任的应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。这里的关键是一次登录,以及一次退出,都对所有的系统生效。
在普通的登录中,比如典型的B/S情景,浏览器访问服务器,发送登录请求,在发送完用户名和密码之后,服务器会生成该用户的session来标准该用户的状态,比如已登录还是已注销,并给一个cookie给浏览器,因此,用户继续访问就会带上这个cookies,服务端会根据这个Cookie找到对应的session,通过session来判断这个用户的登录状态。比如php中使用phpsessid。当然也可以自定义session的生命周期,session的生命周期过长的话一旦session被盗用就会出现用户被窃取的情况。同时,生命周期过长的session配置会占用较多的服务器资源。
单点登录主要针对同平台下多应用,多系统的情景下多次登录的一种解决方案。单点登录相当于将多个应用的认证体系联通。
假设现在一个平台上有3个都带有登录功能的应用,由上面的普通登录的情况可以想到,这3台服务器都会自己的记录session。那么要想达到单点登录,一个最简单的方法就出现了:共享session。
共享session的方式来实现单点登录是最方便也是最直接的。在三个子系统中,使用同一个额外的记录session的服务器,比如我们可以使用一个redis服务器来存储三个系统的session。
用户登录了应用1,获取了应用1返回的cookies,再次访问应用1的其他功能的候携带了cookie就是已登录的状态了,但是这样又有新的问题,虽然实现了共享session,但是用户登录了应用1,获取了应用1返回的cookie,但是因为cookie是无法跨域的,因此用户无法使用应用1的cookie去访问应用2。这里我们就需要将系统的全局cookie domain的属性设置为顶级域名,比如应用1的域名是1.test.com,应用2的域名是2.test.com。在普通登录的情况下,应用1的cookie domain的属性是1.test.com,指这个cookie只能在该子域名上被使用。我们将系统的全局cookie domain设置为顶级域名,即.test.com,这样就可以实现用户登录了应用1,之后可以以已登录状态访问应用2和3。
上面的共享session的情况是三个应用都有登录功能,还有一种类似的情况是应用1和应用2都有登录模块和其他模块,还有一个单独的SSO系统,是仅有登录模块的:
共享session的方法虽然简单,但是存在局限性,因为使用了cookie顶域的特性,所以不能做到跨域。一个公司或者一个平台很可能不是所有的域名都在在一个一级域名之下的,所以同域名下的单点登录并不是完整的单点登录。
先说说openid,openid是一种认证标准,规定如何认证的标准!即其关注的是登录时身份的认证。官方给出的一个场景,其中一方是一个openid身份服务器,用来存放注册好的openid账号,另一方是受这个openid身份服务器信赖的服务或应用。openid协议就是提供openid身份服务器和被信赖的服务或应用之间的通信的。比如我们在很多网站上可以使用QQ登录,这里的腾讯的QQ就是openid的身份服务器,我们所要登录的网站就是受信赖的服务或应用。
在使用openid实现单点登录的方法有很多,可以使用上面共享session的方法,即把openid带在cookie里面,但是这样也会出现一样的cookie跨域的问题。
在实际场景中,我们在访问提供服务的应用时检测到未登录就会直接跳转到openid身份服务器,或者没有重定向而是在登录表单附近点击选择使用第三方openid登录,进行账号密码登录(这可以保证我们所登录的服务器无法获取我们的敏感身份认证信息),具体流程如下:
CAS全称为Central Authentication Service即中央认证服务,是一个企业多语言单点登录的解决方案,并努力去成为一个身份验证和授权需求的综合平台。CAS就是一个现成的单点登录的demo,企业只需要简单修改就可使用。
CAS支持各种协议,SAML,OAuth,OpenID,OIDC等等,支持LDAP,Radius,JWTX,509等等进行身份认证和授权,还有各种常用语言的客户端,Java,PHP,C# 等等。反正就是一个十分完整的,兼容性特别好的SSO框架。
简单了解CAS是如何实现单点登录的。在官网上可以看到其给出的一个 流程图 ,。这个图说的特别详细,一下就能看懂,直接原图上进行标注查看:
学习了上面几种单点登录的知识,结合实际场景可知,跨域单点登录才是真正的单点登录,因为实际情况下很多平台或者域名不可能都在一个一级域名下。在解决跨域单点登录的问题的时候,上面也给说了几种方式,但是究其根本,就是利用一个SSO认证中心来实现认证与授权的。当然,也会有其他的解决跨域单点登录的方案,但是大体流程都与cas类似。
比如在上图的11步骤,也可使用POST包,或者JSONP和iframe方法来跨域发送请求进行重定向。
在利用认证中心来实现单点登录是现在比较普遍的解决方案,那么有没有不需要使用认证中心来解决跨域单点登录的方案呢?
利用JSONP同步登录状态,大概流程流程如下:
在学习单点登录的过程中,在其中认证的过程中授权令牌的传递等相关信息没有特别详细的说明,而且在思考单点登录的时候也会有想过一个比较矛盾的问题:单点登录的目标是为了让用户可以在相互信任的系统中一次登录即可,但是如果真的是做到所有用户都可以访问所有系统,岂不是会带来越权的问题,是否需要对不同的用户以不同的授权,甚至限制访问的应用,但是这样是不是就不是原本狭义的单点认证?
在说单点登录的认证和授权之前,先谈一谈我一直想弄清楚的统一身份认证和单点登录的区别。说起单点登录可能很少听过,但是统一身份认证肯定不陌生,不管是企业还是高校都会有这种统一身份认证的系统。
统一身份认证最重要的一方面就是身份认证,另一方面就是和身份认证相关的授权控制,权限控制。而单点登录是多应用一次登录,也可以叫统一登录,可以理解为主要在认证方面。对于统一身份认证来说会有账号管理,如LDAP,认证管理OAuth,SMAL等,因此我觉得,统一身份认证一般是包括狭义的单点登录,狭义的单点登录,即只需要满足多应用一次登录即可。但是现在的单点登录,SSO系统并不仅仅是要求这些,他的范围正在慢慢扩大。
单点登录的认证和授权,前面说到的CAS实现单点登录里就会看到需要ticket来进行认证,授权。CAS支持多种认证方案,比如OAuth,OpenID,SAML等等,我们可以来比较比较用这些协议的区别,或者说是在哪些场景下使用哪些认证方案较为合适。本身单点登录是没有权限控制的功能的,但是因为这些认证协议的需求,自然支持了权限控制。
在使用SAML进行认证的过程中,可以看到下图,其是基本流程都差不多,这里需要注意的就是在用户在认证中心成功登陆之后,重定向的时候返回的是一个SAML token,一个XML节点,这里的token会包括用户的身份信息,用户名等。
在OAuth2.0的标准中流程是和上面的基本相同,但是OAuth2因为客户端并没有一点是浏览器,所以token中默认是没有签名的。这里可能没有体现出来,OAuth2的目标是授权,所以token更关注的是权限,token在向认证服务器验证的时候就会有不同的授权,但是既然是授权,就间接实现了认证。
在传统的认证中都是基于session机制的,具体的session模式上面也说了,根据其特性可知session的一些确定:
https://www.mutuallyhuman.com/blog/choosing-an-sso-strategy-saml-vs-oauth2/
https://yq.aliyun.com/articles/636281
https://juejin.im/post/5d0dbb7e6fb9a07f0420512d
4. sso通信超时什么意思
简介
SSO是单点登录的简称,常用的SSO的协议有两种,分别是SAML和OAuth2。本文将会介绍两种协议的不同之处,从而让读者对这两种协议有更加深入的理解。
SAML
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协议是怎么处理的。
用户通过User Agent请求Service Provider,比如:
- http://sp.flydean.com/myresource
如果在第一步的时候,SP并没有找到相应的有效安全上下文的话,则会生成对应的SAMLRequest,并将User Agent重定向到IdP:
- 302 Redirect
- Location: https://idp.flydean.com/SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token
User agent将会发送一个get请求到IdP的SSO server :
- GET /SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token HTTP/1.1
- Host: idp.flydean.com
用户可以输入用户名密码进行登录。登录成功之后,IdP将会返回一个XHTML form:
- ...
- form>
user agent 收到XHTML form之后将会提交该form给SP。
SP中的assertion consumer service将会处理这个请求,创建相关的安全上下文,并将user agent重定向到要访问的资源页面。
user agent再次请求SP资源。
因为安全上下文已经创建完毕,SP可以直接返回相应的资源,不用再次到IdP进行认证。
SP将会对该资源进行相应的安全检查,如果发现已经有一个有效的安全上下文的话,SP将会跳过2-7步,直接进入第8步。
RelayState是SP维护的一个状态信息,主要用来防止CSRF攻击。
其中这个SAMLRequest是用Base64编码的 ,下面是一个samlp:AuthnRequest的例子:
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="aaf23196-1773--474a-fe114412ab72"
Version="2.0"
IssueInstant="2020-09-05T09:21:59Z"
AssertionConsumerServiceIndex="0"
="0">
https://sp.flydean.com/SAML2saml:Issuer>
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
samlp:AuthnRequest>
为了安全起见,SAMLRequest还可以使用SP提供的签名key来进行签名。
IdP收到这个AuthnRequest请求之后,将会进行安全验证,如果是合法的AuthnRequest,那么将会展示登录界面。
这个form中包含了SAMLResponse信息,SAMLResponse中包含了用户相关的信息。
同样的SAMLResponse也是使用Base64进行编码过的 。
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="identifier_2"
InResponseTo="identifier_1"
Version="2.0"
IssueInstant="2020-09-05T09:22:05Z"
Destination="https://sp.flydean.com/SAML2/SSO/POST">
https://idp.flydean.com/SAML2saml:Issuer>
Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
samlp:Status>
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="identifier_3"
Version="2.0"
IssueInstant="2020-09-05T09:22:05Z">
https://idp.flydean.com/SAML2saml:Issuer>
我们可以看到samlp:Response中包含有saml:Assertion信息。
我们可以看到上面的所有的信息交换都是由前端浏览器来完成的,在SP和IdP之间不存在直接的通信。
这种全部由前端来完成信息交换的方式好处就是协议流非常简单,所有的消息都是简单的GET或者POST请求。
如果为了提高安全性,也可以使用引用消息。也就是说IdP返回的不是直接的SAML assertion,而是一个SAML assertion的引用。SP收到这个引用之后,可以从后台再去查询真实的SAML assertion,从而提高了安全性。
SAML的缺点
SAML协议是2005年制定的,在制定协议的时候基本上是针对于web应用程序来说的,但是那时候的web应用程序还是比较简单的,更别提对App的支持。
SAML需要通过HTTP Redect和HTTP POST协议来传递用户信息,并且通常是通过HTML FORM的格式来进行数据的提交的。如果应用程序并不是web应用,比如说是一个手机App应用。
这个手机APP应用的启动链接是 my-photos://authenticate , 但是手机app可能并不能获取到Http POST的body内容。他们只能够通过URL来进行参数的传递。
这就意味着,在手机APP中不能够使用SAML。
当然,要想工作也可以,不过需要进行一些改造。比如通过第三方应用对POST消息进行解析,然后将解析出来的SAMLRequest以URL参数的形式传递给APP。
另一种方法就是使用OAuth2.
OAuth2
因为Oauth2是在2012年才产生的。所以并没有那么多的使用限制。我们可以在不同的场合中使用OAuth2。
我们先来看一下OAuth2中授权的流程图:
一般来说OAuth2中有4个角色。
resource owner:代表的是资源的所有者,可以通过提供用户名密码或者其他方式来进行授权。通常来是一个人。
resource server:代表的是最终需要访问到资源的服务器。比如github授权之后获取到的用户信息。
client:用来替代resource owner来进行交互的客户端。
authorization server:用来进行授权的服务器,可以生成相应的Access Token。
整个流程是这样的:
Client向resource owner发起一个授权请求,resource owner输入相应的认证信息,将authorization grant返回给client。
client再将获取到的authorization grant请求授权服务器,并返回access token。
client然后就可以拿着这个access token去请求resource server,最后获取到受限资源。
OAuth2的缺点
OAuth2并没有指定Resource Server怎么和Authorization Server进行交互。也没有规定返回用户信息的内容和格式。这些都需要实现方自己去决定。
OAuth2默认是在HTTPS环境下工作的,所以并没有约定信息的加密方式。我们需要自己去实现。
最后,OAuth2是一个授权协议,而不是认证协议。对于这个问题,其实我们可以考虑使用OpenID Connect协议。因为OpenID Connect就是基于OAuth2实现的,并且添加了认证协议。
OpenID Connect简称为OIDC,已成为Internet上单点登录和身份管理的通用标准。它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议。
OAuth2实际上只做了授权,而OpenID Connect在授权的基础上又加上了认证。
OIDC的优点是:简单的基于JSON的身份令牌(JWT),并且完全兼容OAuth2协议。
两者的对比
在SAML协议中,SAML token中已经包含了用户身份信息,但是在OAuth2,在拿到token之后,需要额外再做一次对该token的校验。
但是另一方面,OAuth2因为需要再做一次认证,所以可以在 Authorization Server 端对token进行无效处理。
CAS简介
做过SSO的应该都听说过CAS。CAS的全称是Central Authentication Service,是一个企业级的开源的SSO认证框架。
CAS内部集成了CAS1,2,3,SAML1,2,OAuth2,OpenID和OpenID Connect协议,非常的强大。我们会在后面的文章中介绍CAS的使用。
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...ds:Signature>
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">
3f7b3dcf-1674-4ecd-92c8-1544f346baf8
saml:NameID>
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
InResponseTo="identifier_1"
Recipient="https://sp.flydean.com/SAML2/SSO/POST"
NotOnOrAfter="2020-09-05T09:27:05Z"/>
saml:SubjectConfirmation>
saml:Subject>
NotBefore="2020-09-05T09:17:05Z"
NotOnOrAfter="2020-09-05T09:27:05Z">
https://sp.flydean.com/SAML2saml:Audience>
saml:AudienceRestriction>
saml:Conditions>
AuthnInstant="2020-09-05T09:22:00Z"
SessionIndex="identifier_3">
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
saml:AuthnContextClassRef>
saml:AuthnContext>
saml:AuthnStatement>
saml:Assertion>
samlp:Response>