【51CTO.com快译】作为一种在各个服务之间交换认证和授权信息的方法,安全断言标记语言(Security Assertion Markup Language,SAML)2.0经常被企业用在构建内部单点登录(single sign-on,SSO)方案的过程中,以实现用户登录到统一的身份认证服务处,进而授予他们对于其他内部服务子集的访问权限。
从安全角度来看,采用SAML/SSO的优势主要体现在如下方面:
- 提供单一的身份来源。当有员工加入或离开公司时,您既不必事无巨细地去更新每一项内部服务,又不必担心错过某个关联性的重要服务。
- 强制执行一致性的认证。可实施SAML/SSO的方法包括:多因素认证和会话持续时间等。
下面,我们将重点讨论SSO和SAML2.0的认证机制与重要性。
SAML的相关术语
主体(Principal)
主体是参与认证的用户。您可以将其视为屏幕后面的实际访问者。在下文中,我们将其假设为John Smith。主体通常会带有诸如:名字、姓氏、电子邮件地址等附加的元数据(metadata)。此类元数据往往也被称为身份信息(identity information),下面我们将重点阐述其重要性。
身份提供者(Identity Provider)
身份提供者常被简称IdP,是提供身份信息和认证判断的源服务。我们可以将身份提供者视为包含身份信息的数据库。它能够认证主体,并将身份信息返回给服务提供者(详见下文)。其中,最常见身份提供者应用包括:Auth0、活动目录联合服务(Active Directory Federation Services,ADFS)和Okta。在实践中,人们往往会将组织的所有用户身份都整合到一个身份提供者处。
服务供应者(Service Providers)
服务提供者通常被缩写为SP,是向主体要求进行认证和获取身份信息的服务。服务提供者获取由身份提供者提供的认证响应,并使用该信息来创建和配置各种会话。也就是说,服务提供者是某个应用程序,它通过为其用户提供单点登录(SSO)机制,来实现资源的登录和访问。
此类应用程序除了知晓主体的名称或邮件地址以外,还需要请求获得主体的其他身份信息,以实现基于角色的访问控制(role-based access control,RBAC)。典型的服务提供者应用包括:Github、Google Apps、以及Teleport(针对SSH和Kubernetes的一种访问解决方案)。
流程(Flows)
目前,SAML支持两种不同类型的流程:由服务提供者初始化的流程、以及由身份提供者初始化的流程。服务提供者初始化的流程往往是从服务提供者开始,被重定向到身份提供者处进行认证,然后在被重定向回服务提供者。该流程通常在用户单击“使用SSO登录”按钮时被启动。
绑定(Bindings)
绑定是指在服务提供者和身份提供者之间传输的数据格式。HTTP重定向绑定和HTTP POST绑定是目前最为流行的两种模式。其中,HTTP重定向绑定使用HTTP重定向和查询参数来传输数据;此类绑定通常被用在认证的请求中。HTTP POST绑定则使用各种HTTP POST表单来传输数据,此类绑定通常被用在认证的响应中。
断言(Assertions)
断言是身份提供者对主体所做的声明,包括:主体的电子邮件地址、与之关联的组或角色等。服务提供者使用断言为主体创建和配置会话。也就是说,断言定义了身份提供者在向服务提供者传送的过程中,包含了主体具有哪些身份信息。
SAML的登录流
为了说明SAML登录的工作原理,我们将在如下示例中使用Teleport作为服务提供者,使用Auth0作为身份提供者。SAML登录的基本流程,如下图所示:
1. 用户单击“通过Auth0登录”按钮,选择使用SAML登录,而不是使用Teleport的内置用户数据库。Teleport会将用户重定向到Auth0处。在此,用户便是SAML中的主体。
2. Auth0要求用户提供他们的用户名(或电子邮件)、密码、以及认证令牌作为第二认证因素(2FA)。
3. 如果提供的信息正确,Auth0将获取主体的身份信息,并将其作为断言返回给Teleport。
4. Teleport会从Auth0处接收到身份信息,进而创建用户会话。
配置
身份提供者往往拥有自己独特的配置方法。下面是身份提供者与服务提供者在协作时需要的最少配置集:
- 断言消费者服务(Assertion Consumer Service,ACS)的URL是服务提供者的端点,身份提供者将其认证的响应重定向到该端点处。由于它将被用于传输个人身份信息(Personally Identifiable Information,PII),因此该端点应当被配置为HTTPS类型。
- 生成并上传用于签发认证请求的签名密钥(详见下文)。
- 对断言中所包含的有关主体信息的来源和格式进行配置。身份提供者至少需要发送NameID、以及组成员等信息。
服务提供者的配置通常比较简单,并且可以通过解析身份提供者所提供的元数据,来自动完成配置。如下Django(译者注:一个开放源代码的Web应用框架,由Python编写而成。)代码段展示了简单的身份提供者元数据的XML。其中,最重要的标签当属SingleSignOnService和KeyDescriptor。具体而言,SingleSignOnService标签定义了有待发送认证请求的绑定和端点,而KeyDescriptor标签则包含了有待认证响应的身份提供者的公钥。
- <md:EntityDescriptor>
- <md:IDPSSODescriptor>
- <md:KeyDescriptor use="signing">
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
- MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
- MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
- NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
- AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
- AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
- CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
- fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
- AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
- FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
- BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
- oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
- kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
- <md:NameIDFormat>
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
- </md:NameIDFormat>
- <md:SingleSignOnService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
- Location="https://idp.example.com/saml"/>
- <md:SingleSignOnService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
- Location="https://idp.example.com/saml"/>
- </md:IDPSSODescriptor>
- </md:EntityDescriptor>
认证请求
在主体登录的过程中,服务提供者会创建一个AuthnRequest的XML文档,通过对其序列化(可采用base64、压缩和URL编码),将其作为查询参数添加到URL中,并将主体的浏览器重定向到身份提供者的登录页面处。服务提供者会请求身份提供者以HTTPS的方式,代为执行认证。如下URL示例便是由HTTP重定向使用绑定AuthnRequest发送的:
- https://idp.example.com/saml?SAMLRequest=nFdpk6JK0%2F0rHc7...
如下Django代码段展示了由AuthnRequest编码的SAMLRequest简化参数:
- <md:IDPSSODescriptor>
- <md:KeyDescriptor use="signing">
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
- MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
- MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
- NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
- AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
- AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
- CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
- fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
- AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
- FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
- BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
- oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
- kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </md:KeyDescriptor>
- <md:NameIDFormat>
- urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
- </md:NameIDFormat>
- <md:SingleSignOnService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
- Location="https://idp.example.com/saml"></md:SingleSignOnService>
- <md:SingleSignOnService
- Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
- Location="https://idp.example.com/saml"></md:SingleSignOnService>
- </md:IDPSSODescriptor>
- /md:EntityDescriptor>"
服务提供者会生成一个较大的安全随机数,并将其插入AuthnRequest标签中的ID字段。该值通常会被存储在本地数据库中,可用于将请求与来自身份提供者的响应进行比对,以防止恶意的第三方在不知道ID的情况下,发送未经请求的响应。
同时,为了防止重复使用已过期的AuthnRequests,身份提供者需要存储和跟踪那些已被使用过的ID值。可见,如果没有时间限制的话,这将会导致身份提供者所需的存储量不断攀升。而IssueInstant恰好可以为请求产生有效的窗口。
服务提供者负责签发AuthnRequest。而在SAML的签名方案中包含了:签名、用于签发请求的密钥、以及有关如何在Signature标签中计算签名的所有信息。因此身份提供者不仅应该认证用于签发请求的密钥,还应该认证该密钥是否与在配置时上传的密钥为同一个(请参阅上一节)。如果密钥或签名值不匹配、或丢失的话,身份提供者就会判定请求为非法,并直接拒绝之。实际上,SAML会使用XML数字签名来签发请求的内容,其本身是一个庞大而复杂的主题。您可以通过链接--https://www.di-mgt.com.au/xmldsig.html,来进一步了解如何使用XMLDSIG去签发XML文档。
认证响应
接着,让我们回到认证的流程。如果主体输入了正确的登录凭据,身份提供者将会对服务提供者的ACS URL(例如,在本示例中为--https://sp.example.com/saml/acs)执行“302重定向”。其正文中包含了认证的响应。如下的Django代码段是一个简化版的SAMLResponse:
- saml2p: Response
- Destination=\"https://sp.example.com/saml/acs\"
- ID=\"id35287812421219341967493380\"
- InResponseTo=\"bcf0b634-67b4-4dc9-a436-4e5cfcfb80e2\"
- IssueInstant=\"2019-04-18T18:51:46.729Z\">
- <ds:Signature>
- <ds:SignedInfo>
- <ds:CanonicalizationMethod
- Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />
- <ds:SignatureMethod
- Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\" />
- <ds:Reference URI=\"#id35287812421219341967493380\">
- <ds:Transforms>
- <ds:Transform
- Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" />
- <ds:Transform
- Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\",/>
- </ds:Transforms>
- <ds:DigestMethod
- Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\" />
- <ds:DigestValue>
- tyLUm4r2isgN+L6sRcqDSEa1Zb7WQbQJG6PpLcf3Mrc=
- </ds:DigestValue>
- </ds:Reference>
- </ds:SignedInfo>
- <ds:SignatureValue>
- XjqbZty/QkqTnMV8YsS2XJ3qgVLPGNC67o/WmzkzoAyl3SBOCGllV4UdijkTjhgykQP7MVXyCql0
- eRtIMJ++rbi3OxCSc0LN67znuTS7cAfcOQzYBtYX2R9w3GlEAO0kZusWYlP3cu/ObmQZUQ7CSgr4
- DRXsVWRhSmmpxHl6klC6c10eWiIlK7Ccpvvvb2hlwl8anyuO/CcKH0n/Rb9vHWtsAlqKXZ8G4X6M
- 77AfRFC7yDWk+8B784109phQxcxoDYjuQNO5IkiRE6J2LnkmuaPoKVyTtpP2JYLiYMSBu8laDsnZ
- I/ewOtBwr16j9oOJpgHPQufQJfvcg+rPEwkptg==
- </ds:SignatureValue>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
- MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
- MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
- NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
- AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
- AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
- CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
- fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
- AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
- FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
- BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
- oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
- kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </ds:Signature>
- <saml2p:Status>
- <saml2p:StatusCode
- Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\" />
- </saml2p:Status>
- <saml2:Assertion
- ID=\"id35287812421980111258419174\"
- IssueInstant=\"2019-04-18T18:51:46.729Z\">
- <ds:Signature>
- <ds:SignedInfo>
- <ds:CanonicalizationMethod
- Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\" />
- <ds:SignatureMethod
- Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\" />
- <ds:Reference URI=\"#id35287812421980111258419174\">
- <ds:Transforms>
- <ds:Transform
- Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\" />
- <ds:Transform
- Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/>
- </ds:Transforms>
- <ds:DigestMethod
- Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\" />
- <ds:DigestValue>
- VKPsgTPABNq1SvInCMXd04LZCvRYMnJzEeT5oIs70hw=
- </ds:DigestValue>
- </ds:Reference>
- </ds:SignedInfo>
- <ds:SignatureValue>
- gsUzQuivXX378HkYNI+plBkp1BvPUNmJD+kh825nHwIBNd019IxffVmOfRAQAkZhT6rqxWhO5/Yc
- JGR5J0qjJVmrRrJ/ipT4VfuJsbn346nEFSMU15D0h3UHrvl651C+NStyXsi8Q8502Qe0ChHOtEXM
- rw9HWPwYtJX0rlpNEzLUnEQPvJ4pd3bz9SIl/YXMNTxE7NCDOxPXKtA4namkkweilxTCynM6A1kn
- 6gEWaXhLMwLLAV6kOtivdVksBPzR9BeZ7RPpXeqt0qN62L4NaHq3OsdjgtQr9sllssD1fEek1eU4
- giCzPgb1+LjvD9dpFH5pcLt9YlwHyYgEBBLOQg==
- </ds:SignatureValue>
- <ds:KeyInfo>
- <ds:X509Data>
- <ds:X509Certificate>
- MIICMjCCAZugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA2MQswCQYDVQQGEwJ1czEL
- MAkGA1UECAwCQ0ExDDAKBgNVBAoMA2lkcDEMMAoGA1UEAwwDaWRwMB4XDTE5MDQy
- NjE4NTIxOFoXDTIwMDQyNTE4NTIxOFowNjELMAkGA1UEBhMCdXMxCzAJBgNVBAgM
- AkNBMQwwCgYDVQQKDANpZHAxDDAKBgNVBAMMA2lkcDCBnzANBgkqhkiG9w0BAQEF
- AAOBjQAwgYkCgYEA1mKmlbr/SiHOhgdROpYeze96mw0WbO+BdJYDceeuNkaw0zOU
- CKZI6TNgrNsqEnLOyWYy5ywA9XA6Ni2qQTuKqapsMT3I1s9DMUg2ln7tTzNdhE02
- fY4GVjiCw7i9YJ+cgcMZh8qL0yoilrLpRLzLrRC6rApqYfEwn+5FPKtTt7cCAwEA
- AaNQME4wHQYDVR0OBBYEFNvFMRtHJ4D327dbRbxhWceXnwd0MB8GA1UdIwQYMBaA
- FNvFMRtHJ4D327dbRbxhWceXnwd0MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN
- BQADgYEAX0I5zpGqI7vzzs8CDyokux1JZzfu+O3P5GfOwUaIG9y01FzxgbL2MRKQ
- oTXMAed97Q6vHA5cffvteu/rPcerpGmFj5h3wv5u+D0ch5s/Mk/Ug6S+x6k3CC+P
- kHimi6OEslFecDMhghUtPJAmhOGnTRwLr7hVeJXBHXWCTXA7aGE=
- </ds:X509Certificate>
- </ds:X509Data>
- </ds:KeyInfo>
- </ds:Signature>
- <saml2:Subject>
- <saml2:NameID>
- jsmith@example.com
- </saml2:NameID>
- <saml2:SubjectConfirmation>
- <saml2:SubjectConfirmationData
- InResponseTo=\"bcf0b634-67b4-4dc9-a436-4e5cfcfb80e2\"
- NotOnOrAfter=\"2019-04-18T18:56:46.730Z\"
- Recipient=\"https://sp.example.com/saml/acs\" />
- </saml2:SubjectConfirmation>
- </saml2:Subject>
- <saml2:Conditions
- NotBefore=\"2019-04-18T18:46:46.730Z\"
- NotOnOrAfter=\"2019-04-18T18:56:46.730Z\"
- xmlns:saml2=\"urn:oasis:names:tc:SAML:2.0:assertion\">
- </saml2:Conditions>
- <saml2:AuthnStatement
- AuthnInstant=\"2019-04-18T18:51:46.729Z\"
- SessionIndex=\"bcf0b634-67b4-4dc9-a436-4e5cfcfb80e2\">
- </saml2:AuthnStatement>
- <saml2:AttributeStatement>
- <saml2:Attribute
- Name=\"logins\">
- <saml2:AttributeValue>
- root
- </saml2:AttributeValue>
- <saml2:AttributeValue>
- jsmith
- </saml2:AttributeValue>
- </saml2:Attribute>
- <saml2:Attribute
- Name=\"groups\">
- <saml2:AttributeValue>
- admins
- </saml2:AttributeValue>
- <saml2:AttributeValue>
- developers
- </saml2:AttributeValue>
- </saml2:Attribute>
- </saml2:AttributeStatement>
- </saml2:Assertion>
- </saml2p:Response>
当服务提供者接收到认证响应时,应当检查InResponseTo属性所引用的AuthnRequest的ID,是否由真实的服务提供者所发送。同时,IssueInstant属性可以用来确定响应的有效性窗口的范围。
由于认证响应被传递到ACS URL处时并不会执行客户端认证,因此这就是为什么我们需要Signature去认证响应中的客户端,是否为真实的身份提供者的原因。这与webhooks(一种自动化部署)的概念非常相似:那些被用于认证客户端的信息(在webhooks中通常是指API密钥)需要提前在带外完成交换。
对应的响应中有着四个新的标签:Status、Subject、Conditions、以及AttributeStatement。其中:
- Status包含了认证是否成功的结果。
- Subject标识了通过认证的主体。例如在上例中,NameID标签就包含了认证主体的电子邮件地址:jsmith@example.com。
- Conditions定义了断言的限制。例如,NotBefore和NotOnOrAfter属性定义了断言有效期的持续时长。这样可以防止恶意行为者通过记录有效的认证响应,进行重放(replaying)攻击。
- AttributeStatement包含了身份提供者针对主体所做出的断言。如前所述,断言通常会包含诸如:组织内部的组成员身份、受允许的登录、以及有关主体的其他识别信息。在上例中,该主体属于admins和developers组,并被允许以root和jsmith身份登录。
可见,我们需要记住的是:主体的断言只是在识别信息时的一个快照,如果提供长期存在(long-lived)的断言、或会话,就会存在安全隐患。因此,我们需要让断言和会话保持合理且短暂(short-lived),以及通过强制性的重新认证,来确保身份提供者对主体所做出的断言的有效性。
小结
综上所述,服务提供者会根据判断的结果,来提供响应。只有成功的响应才会在内部服务中创建会话,提供单一的身份源,以及实现横跨内部服务的一致性认证。为此,服务提供者通常需要知道主体所属的用户组,并据此实施基于角色的访问控制策略。例如,只有来自“SSH”组的用户,才能够访问生产环境;而其他组的用户,则需要根据不同的策略,去访问Kubernetes集群、或CI/CD管道。
总的说来,SAML认证解决了如下三个重要问题:
- SAML显著改善了用户的体验。用户只需要记住他们常用的单一身份凭据,而不必针对不同的应用,使用不同的用户名和密码。
- SAML允许应用程序开发人员将身份管理和认证实施,外包给外部的提供者,而无需自行实现。
- 最重要的是,SAML显著降低了组织内针对访问管理的运营开销。如果有员工离开或转移到其他团队,他们的访问权限将会在连接到身份提供者所对应的应用时,自动被撤销或降级。
原文标题:How SAML 2.0 Authentication Works and Why It Matters,作者:Ev Kontsevoy
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】