快速理解SAML2.0

SAML,全称为Security Assertion Markup Language,是一种用于安全性断言的标记语言,目前的最新版本是2.0。

它是一个基于XML的标准,用于在不同的安全域(security domain)之间交换认证和授权数据。SAML2.0可以帮助我们跨域实现单点登录。

术语介绍

  • 服务提供方(Service Provider,简称SP),服务提供的实体。举个例子,我们平时使用邮件服务、腾讯云、腾讯会议等软件服务,这类都是服务提供方。

  • 身份提供方(Identity Provider,简称IDP),身份提供的实体,包含对用户进行身份验证的能力。当我们使用企业微信扫码的登录腾讯会议的时候,这里的企业微信其实就可以理解为身份提供方。在SAML协议里,严格规范了IDP和SP之间传输的Token格式。

  • SAML请求(SAMLRequest),由SP生成,发送给IDP的身份验证请求,所以一般也叫做AuthnRequest(Authentication Request)。

  • SAML响应(SAMLResponse),由IDP生成,携带用户身份信息,发送给SP的身份验证结果,所以一般也叫做SAMLAssertion。

  • 服务提供方发起(SP-initiated),表示整个认证流程是由SP发起的,当客户直接访问SP的资源或网站时,跳转到IDP再跳转回来的过程,我们就称这个过程是SP-initiated的单点登录。

  • 认证提供方发起(IDP-initiated),表示整个认证流程是由IDP发起的,IDP直接提供SAML响应给到SP方,验证用户身份。

SAML认证流程

下面介绍的是一个SP-initiated的完整认证流程,IDP-initiated可以理解为是SP-initiated的简化部分。

img

  1. 用户打开SP地址,如访问腾讯云。

  2. SP接收到请求之后,携带SAMLRequest请求到到IDP处(SAMLRequest的格式后面会给出)。

  3. IDP接收到SAMLRequest后,会在IDP验证用户身份,玉符统一身份会检查当前用户是否登录,如果未登录跳转登录页面。

  4. IDP验证身份通过后,会重定向到SP,携带SAMLResponse(SAMLResponse的格式后面会给出)。

  5. SP验证SAMLResponse,验证通过后取出SAMLResponse里携带的用户信息,访问对应的用户。

SAMLRequest介绍

下面是一个SAMLRequest的XML示例

1<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://www.sp.com/saml/acs" Destination="https://www.idp.com/saml/authn" ForceAuthn="false" ID="_7xvtiohf7xupg9ulo8an1g4bemeranpifvup" IsPassive="false" IssueInstant="2019-07-25T09:59:02.467Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
2 <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://www.sp.com</saml2:Issuer>
3</saml2p:AuthnRequest>

SAMLRequest通常以saml2p:AuthnRequest作为XML顶层的名称,配合一些属性描述

  • xmlns:saml2p一般固定为urn:oasis:names:tc:SAML:2.0:protocol

  • AssertionConsumerServiceURL表示服务提供方SP接受SAML断言响应的接口地址,如此处例子中的https://www.sp.com/saml/acs

  • Destination表示身份提供方IDP接受SAML请求的地址,如此处的https://www.idp.com/saml/authn

  • saml2:Issuer表示发起SAML请求的服务提供方SP的身份,此处示例为https://www.sp.com

在实际请求中,还需要将SAMLReqeust进行Base64编码,上文示例的SAMLRequest进行Base64编码之后如下:

1fZFBT8JAEIXvJv6Hzd5pSwPWbigJSowkGhuoHryYpQywSTu77uwWfr6lYISYcJ158+bNNyOSdRUbMfFui3P49kCO7esKSRw7GfcWhZakSKCsgYQrxWLy+iLiIBLGaqdLXXE2IQLrlMZHjeRrsAuwjSrhff6S8a1zhkQY7na7gExQ6jo8uIeyJM6m7UqF8jB7qVSrc+khIGdP2pbQhc34WlYEnM2mGf9K9k1rsF0ne282qa/0vcT+ZrCENolEo9aNN62UckmkGvgbJvIwQ3ISXcbjqJ/2oqQXD4soFcNURHEwuEs+OctPhz4oXCncXKeyPIpIPBdF3svfFgVnH2Cpu7AV8PHtDWOjDrDoEthz5tfN5S9oPv6PdRSem7ZrToXLB49/AA==

当服务提供方SP未登录时,需要跳转到认证提供方IDP的地址,进行身份验证操作,最终生成的URL如下所示:

1https://www.idp.com/saml/authn?SAMLRequest=fZFBT8JAEIXvJv6Hzd5pSwPWbigJSowkGhuoHryYpQywSTu77uwWfr6lYISYcJ158+bNNyOSdRUbMfFui3P49kCO7esKSRw7GfcWhZakSKCsgYQrxWLy+iLiIBLGaqdLXXE2IQLrlMZHjeRrsAuwjSrhff6S8a1zhkQY7na7gExQ6jo8uIeyJM6m7UqF8jB7qVSrc+khIGdP2pbQhc34WlYEnM2mGf9K9k1rsF0ne282qa/0vcT+ZrCENolEo9aNN62UckmkGvgbJvIwQ3ISXcbjqJ/2oqQXD4soFcNURHEwuEs+OctPhz4oXCncXKeyPIpIPBdF3svfFgVnH2Cpu7AV8PHtDWOjDrDoEthz5tfN5S9oPv6PdRSem7ZrToXLB49/AA==

SAMLResponse介绍

当IDP接受到服务提供方SP发起的SAMLRequest时,会在IDP的域内进行身份认证操作,完成登录行为之后,会携带当前登录的用户身份,发送SAMLResponse给到服务提供方SP。

下面是一个SAMLResponse的XML示例

1<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://www.sp.com/saml/acs" ID="_80ff50f0-73e9-4357-934e-15939aa197ae" InResponseTo="_7xvtiohf7xupg9ulo8an1g4bemeranpifvup" IssueInstant="2019-07-25T09:59:01.653Z" Version="2.0">
2 <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://www.idp.com</saml2:Issuer>
3 <saml2p:Status>
4 <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
5 </saml2p:Status>
6 <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ee51e413-cb8c-4cff-a833-8e5ab5a65712" IssueInstant="2019-07-25T09:59:01.653Z" Version="2.0">
7 <saml2:Issuer>https://www.idp.com</saml2:Issuer>
8 <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
9 <ds:SignedInfo>
10 <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
11 <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
12 <ds:Reference URI="#_ee51e413-cb8c-4cff-a833-8e5ab5a65712">
13 <ds:Transforms>
14 <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
15 <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
16 </ds:Transforms>
17 <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
18 <ds:DigestValue>SeLenKpDFTFSrd4RodgCxUbXi1I=</ds:DigestValue>
19 </ds:Reference>
20 </ds:SignedInfo>
21 <ds:SignatureValue>fEN31jRzjpGPSFEazXSYIu8mlhSrB/2rhlGmkQw8vbgUlHveU4BfX91knG11yF4HcLd5686WYWCS9P9szLvcxuQlVi1z5NiIFs967Z3hCZuU6mP86/5qEJVOVeUnaS39YtP8Jwxoev2d4QJjJ0+9+9ifOQkf4bhM+9b8Q1/3A5Q4xqjvArHTwGQMnjpi5hJQprkreChvNXGu3vemzHb5HEGkQHsbwavuA65VDwQ3sxdQbbDjQrXMIZWlKt51IXHhDVrlCwVIDXPCrN1e3wJrkLPitAUbhDCcRdVvmc8a5lcmvX4SkDn7PwzmFAf1rXACCyvKft5YycYnN7zHkymLCA==</ds:SignatureValue>
22 <ds:KeyInfo>
23 <ds:X509Data>
24 <ds:X509SubjectName>C=CN,L=Beijing,CN=com,CN=yufuid</ds:X509SubjectName>
25 <ds:X509Certificate>MIIC/DCCAeSgAwIBAgIIBjRkHLoMipUwDQYJKoZIhvcNAQEFBQAwPjEPMA0GA1UEAwwGeXVmdWlkMQwwCgYDVQQDDANjb20xEDAOBgNVBAcMB0JlaWppbmcxCzAJBgNVBAYTAkNOMB4XDTE5MDcyMzEwNDA1NloXDTIwMDcyMjEwNDA1NlowPjEPMA0GA1UEAwwGeXVmdWlkMQwwCgYDVQQDDANjb20xEDAOBgNVBAcMB0JlaWppbmcxCzAJBgNVBAYTAkNOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0dk/S9XEiBio3CRccVIsjFX4KBGZPfz47jrm9TF1v3t+7Cy7WkYD6EW/rQYi7ORfRTVx8m8UsiB04MjwHARtVdDPP9COxfjkVp5h5nQv1P6WYtZjIFDiIBbS0of1YmeHzCixxGQDk+PL/M19aey9DoRVg9MjcQYppjoiYbJhqj/YL2kCO5QgaquPptBCVKcMpqE1BCggPLyH3M1V7/QJXzRKBs/iOO/3yUnapftK/ysZeWMZ2hEGlB/AW3OP9pO2vijONqxbHqTFyngyYof+QRl7F5KsmZNP5Pd6SoYo0MtrEsDVIchdx9Mb1iCLZfiHqbq8s4mr7+alvuyBE1lW+QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAdz05eOepSmE+IFMdwLkkD5oDBBwC16ie5BpXBxFAYxEYrQ8sZPmjTIhG+tQe3lnkxmrgyPbq1pevybGl3aR9dPWysg3ps2pK+pJQt6aRHQbNhy+fFT4uqZzVXy/61LPt8OhhhzjGVoApIh53A4OuffV2B1PueBChjrrKEZGHk5iVuzv1kEtGu0NIKbTXBcG7ZfX+2pKYYKw3AKllFDSBL/ePFjUh5iXJWwwGflqwtQjmZYZt4k+UMDIW7L6r5FlDNc4JGjH1gWOXpCZ6EkGR1rAmK2Fnv1/5LTRVYrMlGYlCx29DhM7GVnpgfTmua15E3dW+WyS4TOM8UnjavAIBa</ds:X509Certificate>
26 </ds:X509Data>
27 </ds:KeyInfo>
28 </ds:Signature>
29 <saml2:Subject>
30 <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">sanzhang</saml2:NameID>
31 <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
32 <saml2:SubjectConfirmationData InResponseTo="_7xvtiohf7xupg9ulo8an1g4bemeranpifvup" NotOnOrAfter="2019-07-25T10:04:01.647Z" Recipient="https://www.sp.com/saml/acs"/>
33 </saml2:SubjectConfirmation>
34 </saml2:Subject>
35 <saml2:Conditions NotBefore="2019-07-25T09:54:01.647Z" NotOnOrAfter="2019-07-25T10:04:01.647Z">
36 <saml2:AudienceRestriction>
37 <saml2:Audience>https://www.sp.com</saml2:Audience>
38 </saml2:AudienceRestriction>
39 </saml2:Conditions>
40 <saml2:AuthnStatement AuthnInstant="2019-07-25T09:59:01.653Z">
41 <saml2:AuthnContext>
42 <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
43 </saml2:AuthnContext>
44 </saml2:AuthnStatement>
45 </saml2:Assertion>
46</saml2p:Response>

这里的参数比较多,就不一一介绍了,只标记几个关键字段进行解释:

  • 这里的Destination其实表示的是服务提供方SP接收SAML响应的地址,如示例的 https://www.sp.com/saml/acs 。注意一定要跟SAMLRequest里的Destination区分开来。

  • NameID表示登录的用户身份,这里的响应表示登录的用户为sanzhang。

  • SAMLResponse是会指定有效期的,用NotBeforeNotOnOfAfter进行表示,上述示例中,该响应的有效期为2019年7月25日9点54分到2019年7月25日10点54分(北京时间需要增加八小时)。

SAML如何保证响应的有效性

身份提供方IDP需要生成密钥对,用密钥对生成配套的证书,并将证书给到服务提供方SP。SP需要存储证书,当IDP签发SAMLResponse时,会对Response响应进行签名,当SP接受到IDP签发的SAMLResponse时,需要用证书校验签名的有效性。