简介
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 将会对该资源进行相应的安全检查,如果发现曾经有一个无效的平安上下文的话,SP 将会跳过 2 - 7 步,间接进入第 8 步。
- 如果在第一步的时候,SP 并没有找到相应的无效平安上下文的话,则会生成对应的 SAMLRequest,并将 User Agent 重定向到 IdP:
302 Redirect
Location: https://idp.flydean.com/SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token
RelayState 是 SP 保护的一个状态信息,次要用来避免 CSRF 攻打。
其中这个 SAMLRequest 是用 Base64 编码的 <samlp:AuthnRequest>,上面是一个 samlp:AuthnRequest 的例子:
<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-2113-474a-fe114412ab72"
Version="2.0"
IssueInstant="2020-09-05T09:21:59Z"
AssertionConsumerServiceIndex="0"
AttributeConsumingServiceIndex="0">
<saml:Issuer>https://sp.flydean.com/SAML2</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
</samlp:AuthnRequest>
为了平安起见,SAMLRequest 还能够应用 SP 提供的签名 key 来进行签名。
- User agent 将会发送一个 get 申请到 IdP 的 SSO server :
GET /SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token HTTP/1.1
Host: idp.flydean.com
IdP 收到这个 AuthnRequest 申请之后,将会进行平安验证,如果是非法的 AuthnRequest,那么将会展现登录界面。
- 用户能够输出用户名明码进行登录。登录胜利之后,IdP 将会返回一个 XHTML form:
<form method="post" action="https://sp.flydean.com/SAML2/SSO/POST" ...>
<input type="hidden" name="SAMLResponse" value="response" />
<input type="hidden" name="RelayState" value="token" />
...
<input type="submit" value="Submit" />
</form>
这个 form 中蕴含了 SAMLResponse 信息,SAMLResponse 中蕴含了用户相干的信息。
同样的 SAMLResponse 也是应用 Base64 进行编码过的 <samlp:Response>。
<samlp:Response
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">
<saml:Issuer>https://idp.flydean.com/SAML2</saml:Issuer>
<samlp:Status>
<samlp:StatusCode
Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="identifier_3"
Version="2.0"
IssueInstant="2020-09-05T09:22:05Z">
<saml:Issuer>https://idp.flydean.com/SAML2</saml:Issuer>
<!-- a POSTed assertion MUST be signed -->
<ds:Signature
xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
<saml:Subject>
<saml:NameID
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">
3f7b3dcf-1674-4ecd-92c8-1544f346baf8
</saml:NameID>
<saml:SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData
InResponseTo="identifier_1"
Recipient="https://sp.flydean.com/SAML2/SSO/POST"
NotOnOrAfter="2020-09-05T09:27:05Z"/>
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions
NotBefore="2020-09-05T09:17:05Z"
NotOnOrAfter="2020-09-05T09:27:05Z">
<saml:AudienceRestriction>
<saml:Audience>https://sp.flydean.com/SAML2</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement
AuthnInstant="2020-09-05T09:22:00Z"
SessionIndex="identifier_3">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
</samlp:Response>
咱们能够看到 samlp:Response 中蕴含有 saml:Assertion 信息。
- user agent 收到 XHTML form 之后将会提交该 form 给 SP。
- SP 中的 assertion consumer service 将会解决这个申请,创立相干的平安上下文,并将 user agent 重定向到要拜访的资源页面。
- user agent 再次申请 SP 资源。
- 因为平安上下文曾经创立结束,SP 能够间接返回相应的资源,不必再次到 IdP 进行认证。
咱们能够看到下面的所有的信息替换都是由前端浏览器来实现的,在 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 的应用。
本文作者:flydean 程序那些事
本文链接:http://www.flydean.com/saml-vs-oauth2/
本文起源:flydean 的博客
欢送关注我的公众号:「程序那些事」最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!