全部产品
云市场

SAML2.0对接

更新时间:2019-04-29 10:53:19

前言

安全断言标记语言(英语:Security Assertion Markup Language,简称SAML)是一个基于XML的开源标准数据格式,它在系统之间交换身份验证和授权数据,尤其是在身份提供者和服务提供者之间交换。
IoT支持基于 SAML 2.0 的 SSO(Single Sign On,单点登录),也称为身份联合登录。本文为您介绍当企业希望使用自有的身份系统来实现 SSO 时,通过IoT提供的 SSO 解决方案,帮助企业实现与IoT的 SSO。

术语

  • 身份提供商(IDP, Identity Provider),身份提供商,在本案例中,是三方oc平台承担
  • 服务提供商(SP, Service Provider),服务提供商,在本案例中,由IOT平台承担
  • 断言(Assertion),由IDP颁发,标识用户账号或身份数据,用于建立登录态
  • 证书(Certificate),用于数据加签或者加密,可以配置不同的证书,用于加签和加* 密,SAML使用自签的x509证书
  • BuyApp,三方购买的应用,与阿里云iot域名不同
  • isv_oc,三方的运营平台,与阿里云iot域名不同
  • ISV_AuthServer: 三方认证服务器

认证过程

流程示意图

image.png

  1. ISV导入IoT SAML证书,认证callback地址,并将自有账户体系同步至IoT
  2. 用户进入三方应用的登录页面,输入用户名及密码后,IDP进行身份确认
  3. IDP页面重定向到IoT SAML认证地址
  4. SP进行证书验证及有效性判断,并建立IoT用户登录态
  5. SP页面重定向到callback url地址(一般为三方应用的主页)

系统调用图


sep整理-Page-9.png

接入流程

Step1. 密钥生成

(1) 生成RSA私钥

  1. openssl genrsa -aes128 -passout pass:${password} -out rsa_aes_private.key 2048

(2) 生成证书请求文件

  1. openssl req -new -key rsa_aes_private.key -passin pass:${password} -out client.pem #可以添加上-days 365参数延长证书有效期

_
(3) 生成最终的SAML使用的x509证书

  1. openssl req -x509 -key rsa_aes_private.key -in client.pem -out client.pem

(4) 通过以上2步之后会获取2个文件,一个是rsa_aes_private.key 这个是密钥,密钥自己妥善保存,如果泄露则所在的租户账户都将面临风险,证书用于生成SAML元数据是可以对外公布的。

Step2. 生成IDP元数据

可参考demo中的com.aliyun.iotx.samldemo.controller.SAMLController#metadata函数来查看如何生产元数据文件

Step3. 导入IDP元数据

登录SI工作台,创建项目并设置自有账户体系>导入step2中生成的元数据文件,并填写saml call back 地址

Step4. 创建公司

详情参见组织管理相关接口,创建相关组织结构,为导入员工做准备。

Step5. 导入员工

详情参见账户管理相关接口,批量导入应用的账户信息,建议手机号作为用户唯一标识。

Step6. 发起SAML调用

参考demo中的com.aliyun.iotx.samldemo.controller.SAMLController#login函数
image.png

DEMO说明

DEMO下载地址

https://github.com/aliyun/aliyun-iot-account-samlidp-demo

DEMO启动说明

Step1. application.properties设置
  1. iot.saml.companyId=X

companyId为IoT平台建立的公司ID,做SAML认证的相关员工账户需要一个管理主体,这个主体就是公司,所以每次做SAML认证时需要携带员工所属手机号+公司ID才能定位到唯一的员工,详情参见组织管理相关接口,来获取如何创建及查询公司。

  1. iot.saml.host=http://localhost

iot.saml.host 为当前应用的域名,该域名会被作为IDP元数据xml的一部分内容,当发起对接流程中的第三部跳转时,IoT平台和根据IDP元数据xml中的域名来判断请求是否合法。

  1. iot.key.password=xxxxxx

iot.key.password即为生成密钥中使用的${password}参数,为读取公私钥的密码,按需设置。

Step2. client.pem/rsa_aes_private.key替换

将demo中的client.pem/rsa_aes_private.key两个文件替换为接入流程->密钥生成中创建的文件

Step3. run SamldemoApplication

运行com.aliyun.iotx.samldemo.SamldemoApplication

FAQ

  1. Q:提示IDP不存在
  2. A:如果SAML对应的元数据未注册过,请联系阿里云同学注册.如果已经注册过,因为调试或者其他原因修改过SAML对接程序的host,这时候搜索下demo中的assertion.setIssuer(idpBuildIssuer()); 这个代码,确认其返回的结果与注册元信息中的entityId一致.
  3. Q:提示employee not exist
  4. A:请确保公司下面有该人员(手机号),且该手机号能正常登录阿里云IOT OC平台
  5. Q:signature check failed
  6. A:请确保提供的元数据的证书与加签所使用的私钥能够匹配上
  7. Q:org.opensaml.messaging.handler.MessageHandlerException: Message was rejected because it was issued in the future
  8. A:请确保颁发断言的服务器时间与标准时间是否一致
  9. Q:IOT中心没有收到免登录请求
  10. A:因为登录过程需要由当前域名跳转到IOT域名下,因此不可使用异步ajax登录的方式进行登录.
  11. Q:localhost127.0.0.1 能混用吗?
  12. A:不可以,使用localhost或者127.0.0.1注册IDP时,请访问对接应用时使用对应的地址或者IP访问,有refer校验,当访问地址不正确时,refer校验无法通过
  13. Q: refer check failed
  14. A: 同上面问题原因

参考资料

数据格式参考

IDP元数据样例

该样例为接入流程->Step2. 生成IDP元数据中生成的数据样例

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <md:EntityDescriptor entityID="http://localhost:8080/saml/idp/metadata" validUntil="2020-02-26T06:42:53.018Z"
  3. xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
  4. <md:IDPSSODescriptor WantAuthnRequestsSigned="true"
  5. protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
  6. <md:KeyDescriptor use="signing">
  7. <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  8. <ds:X509Data>
  9. <ds:X509Certificate>MIICgTCCAeoCCQCuVzyqFgMSyDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCVVMxEzARBgNV
  10. BAgMCldhc2hpbmd0b24xEjAQBgNVBAcMCVZhbmNvdXZlcjEdMBsGA1UECgwUU3ByaW5nIFNlY3Vy
  11. aXR5IFNBTUwxCzAJBgNVBAsMAnNwMSAwHgYDVQQDDBdzcC5zcHJpbmcuc2VjdXJpdHkuc2FtbDAe
  12. Fw0xODA1MTQxNDMwNDRaFw0yODA1MTExNDMwNDRaMIGEMQswCQYDVQQGEwJVUzETMBEGA1UECAwK
  13. V2FzaGluZ3RvbjESMBAGA1UEBwwJVmFuY291dmVyMR0wGwYDVQQKDBRTcHJpbmcgU2VjdXJpdHkg
  14. U0FNTDELMAkGA1UECwwCc3AxIDAeBgNVBAMMF3NwLnNwcmluZy5zZWN1cml0eS5zYW1sMIGfMA0G
  15. CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRu7/EI0BlNzMEBFVAcbx+lLosvzIWU+01dGTY8gBdhMQN
  16. YKZ92lMceo2CuVJ66cUURPym3i7nGGzoSnAxAre+0YIM+U0razrWtAUE735bkcqELZkOTZLelaoO
  17. ztmWqRbe5OuEmpewH7cx+kNgcVjdctOGy3Q6x+I4qakY/9qhBQIDAQABMA0GCSqGSIb3DQEBCwUA
  18. A4GBAAeViTvHOyQopWEiXOfI2Z9eukwrSknDwq/zscR0YxwwqDBMt/QdAODfSwAfnciiYLkmEjlo
  19. zWRtOeN+qK7UFgP1bRl5qksrYX5S0z2iGJh0GvonLUt3e20Ssfl5tTEDDnAEUMLfBkyaxEHDRZ/n
  20. bTJ7VTeZOSyRoVn5XHhpuJ0B
  21. </ds:X509Certificate>
  22. </ds:X509Data>
  23. </ds:KeyInfo>
  24. </md:KeyDescriptor>
  25. <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
  26. <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
  27. Location="http://localhost:8080/saml/idp/sso"/>
  28. </md:IDPSSODescriptor>
  29. </md:EntityDescriptor>

SAML调用数据样例

该样例为接入流程->Step6. 发起SAML调用中发起请求的数据样例

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://account.iot.aliyun.test/saml/sp/acs" ID="_5676dfe1f94353c748ad240797e38448" IssueInstant="2019-03-20T03:19:17.165Z" Version="2.0">
  3. <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://localhost:8888/saml/metadata</saml2:Issuer>
  4. <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  5. <ds:SignedInfo>
  6. <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  7. <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
  8. <ds:Reference URI="#_5676dfe1f94353c748ad240797e38448">
  9. <ds:Transforms>
  10. <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
  11. <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  12. </ds:Transforms>
  13. <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#ripemd160"/>
  14. <ds:DigestValue>RMAwR0cVg6wgBMpZ3AsDJas08tc=</ds:DigestValue>
  15. </ds:Reference>
  16. </ds:SignedInfo>
  17. <ds:SignatureValue>a9PoPnO5AAteCCZxS5hRFqMtnIIV4XBXcsYITiQf+7YKhGEINruMXp2jJOv+eqq712rZujy295Sx imx66ou5DfjkKRpZsbMw+jKoRZjuLfmOb/F34Z6lAZMU8dFkpltYL+syI70OWmMcvs62WCHrcPGx KLz+enigs7gpJHnEapbJphag2TaWevg85NSWs+gXWR6nrkGB1GuBhjyHBYpD1lFgWofsal87PVM7 R2FSwmHTRoVmmaxCb3sGjiGgUCvtumMktRLOq3LKfxYvfLV89ou05XcZZRqKlSO7p9lRt+AfGB/C RhtOXwtB7fJIK55OyFn51rAtXk+CRtVYGv+R6g==</ds:SignatureValue>
  18. <ds:KeyInfo>
  19. <ds:X509Data>
  20. <ds:X509Certificate>MIIDMjCCAhoCCQD6lwFKgkPKvDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJBQTEKMAgGA1UE CAwBQTEKMAgGA1UEBwwBQTEKMAgGA1UECgwBQTEKMAgGA1UECwwBQTEKMAgGA1UEAwwBQTEQMA4G CSqGSIb3DQEJARYBQTAeFw0xOTAyMTcxMjM4MjVaFw0xOTAzMTkxMjM4MjVaMFsxCzAJBgNVBAYT AkFBMQowCAYDVQQIDAFBMQowCAYDVQQHDAFBMQowCAYDVQQKDAFBMQowCAYDVQQLDAFBMQowCAYD VQQDDAFBMRAwDgYJKoZIhvcNAQkBFgFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA r/Nuy5VN2XqFVyvRm1NFYWLscIuteTILZ0/JkIfU5ZCpr9HziBI5rVYLWUsAt6Pq8Ur1IxTQjRu1 e3O308Oc5rjze0oyDTPUrBJWvJHgwGf16EVNpVCc69BUN4gLzIQqKucRVkUDVS1fTC7L7AhHoMeD o2fb93JlBteH/2TmDKMAatlHjRXOLYUeuXk7M+e72t5wgnHX9t8NpsVZUq84LYD4cQxcMtQua5eP xXV5pdjWjeOFRiBV5dA4b21yNvaO6WByp8pQvGBO0Pi/RVfT+NgzCmDAd+dDRBKDVkLfui9y00b5 Uvz2pD2NrG3j6WU0G4Tnrk28zv0A1TMYg1cqswIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQABvYrL lkI0QfEGxpVXk/B2KBwp9mzuAf9g7W693MXPiSoxZty0OjdPW7DrpZGaSxqoLXf6f9PZtzLdjr+f bvCPwG1liJ+pvDZyK4MCzSUE/SA8vvPbNUDmuoJY44tsCrdmROh1ys4K728pA/oqX3pRMz2jjIeO Xo31ZjADn3r3CGrfX7n37iGPaQqZStepaGw0F0L/hu31yVVWrBDEdgPynMjSxdOzHgvKfwPF74hD nrpC/g3yJhe4KmkKbYdgNXTcSOhTsbhSyldzP/FAG9wx+4iRRXCa8wZnqXiFb2UoiW7SiWmx3tET /OEijFG1aEUJ/R81mI/pw5nyVbYRJldF</ds:X509Certificate>
  21. </ds:X509Data>
  22. </ds:KeyInfo>
  23. </ds:Signature>
  24. <saml2p:Status>
  25. <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  26. </saml2p:Status>
  27. <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_ba4341a4ab83ab70f1e0a755ee8fd8e8" IssueInstant="2019-03-20T03:19:17.165Z" Version="2.0">
  28. <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://localhost:8888/saml/metadata</saml2:Issuer>
  29. <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  30. <ds:SignedInfo>
  31. <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  32. <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
  33. <ds:Reference URI="#_ba4341a4ab83ab70f1e0a755ee8fd8e8">
  34. <ds:Transforms>
  35. <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
  36. <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
  37. </ds:Transforms>
  38. <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#ripemd160"/>
  39. <ds:DigestValue>hLWddfQ0RKXWZAyuoFkDOMX220w=</ds:DigestValue>
  40. </ds:Reference>
  41. </ds:SignedInfo>
  42. <ds:SignatureValue>YR6u3IGEA1cio8/CgUDq1pLPhNn5Dx4WyA1BMEuOh/63I+m0J2CNJ9yb3PoSHWM4mjJNS6B5UFcb ZYvyLvgriA+cNys53TvIOCFI8W0MSlDEhYM6rw+WNoT6uHK8F+zJ5ehlY9/r3PYxmsC+MYwkFFJ6 SemcbcxvrMVubuVVRAiSq/Z1sSt4VPWjiQc57CSm2r1gVys4k83zvpjwpw6OnB2S68+cgC5unLXL mwiS6+6Kw1wSwR4nWD0RsUKU6bCUYgC9WcC61x7/CMJo0tvAJ+pJiRQG7neXTdSlc+oGS+F0hSp3 yfJ07bjYShffyd7QDSKBRdbC61KXkNTIvhtV3g==</ds:SignatureValue>
  43. <ds:KeyInfo>
  44. <ds:X509Data>
  45. <ds:X509Certificate>MIIDMjCCAhoCCQD6lwFKgkPKvDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJBQTEKMAgGA1UE CAwBQTEKMAgGA1UEBwwBQTEKMAgGA1UECgwBQTEKMAgGA1UECwwBQTEKMAgGA1UEAwwBQTEQMA4G CSqGSIb3DQEJARYBQTAeFw0xOTAyMTcxMjM4MjVaFw0xOTAzMTkxMjM4MjVaMFsxCzAJBgNVBAYT AkFBMQowCAYDVQQIDAFBMQowCAYDVQQHDAFBMQowCAYDVQQKDAFBMQowCAYDVQQLDAFBMQowCAYD VQQDDAFBMRAwDgYJKoZIhvcNAQkBFgFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA r/Nuy5VN2XqFVyvRm1NFYWLscIuteTILZ0/JkIfU5ZCpr9HziBI5rVYLWUsAt6Pq8Ur1IxTQjRu1 e3O308Oc5rjze0oyDTPUrBJWvJHgwGf16EVNpVCc69BUN4gLzIQqKucRVkUDVS1fTC7L7AhHoMeD o2fb93JlBteH/2TmDKMAatlHjRXOLYUeuXk7M+e72t5wgnHX9t8NpsVZUq84LYD4cQxcMtQua5eP xXV5pdjWjeOFRiBV5dA4b21yNvaO6WByp8pQvGBO0Pi/RVfT+NgzCmDAd+dDRBKDVkLfui9y00b5 Uvz2pD2NrG3j6WU0G4Tnrk28zv0A1TMYg1cqswIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQABvYrL lkI0QfEGxpVXk/B2KBwp9mzuAf9g7W693MXPiSoxZty0OjdPW7DrpZGaSxqoLXf6f9PZtzLdjr+f bvCPwG1liJ+pvDZyK4MCzSUE/SA8vvPbNUDmuoJY44tsCrdmROh1ys4K728pA/oqX3pRMz2jjIeO Xo31ZjADn3r3CGrfX7n37iGPaQqZStepaGw0F0L/hu31yVVWrBDEdgPynMjSxdOzHgvKfwPF74hD nrpC/g3yJhe4KmkKbYdgNXTcSOhTsbhSyldzP/FAG9wx+4iRRXCa8wZnqXiFb2UoiW7SiWmx3tET /OEijFG1aEUJ/R81mI/pw5nyVbYRJldF</ds:X509Certificate>
  46. </ds:X509Data>
  47. </ds:KeyInfo>
  48. </ds:Signature>
  49. <saml2:Subject>
  50. <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">16657118686</saml2:NameID>
  51. <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
  52. <saml2:SubjectConfirmationData NotOnOrAfter="2019-03-20T03:24:17.165Z" Recipient="https://account.iot.aliyun.test/saml/sp/acs?id=adsf"/>
  53. </saml2:SubjectConfirmation>
  54. </saml2:Subject>
  55. <saml2:Conditions NotBefore="2019-03-20T03:19:17.165Z" NotOnOrAfter="2019-03-20T03:19:22.165Z">
  56. <saml2:AudienceRestriction>
  57. <saml2:Audience>https://account.iot.aliyun.test/saml/sp/metadata</saml2:Audience>
  58. </saml2:AudienceRestriction>
  59. </saml2:Conditions>
  60. <saml2:AuthnStatement AuthnInstant="2019-03-20T03:19:17.204Z" SessionIndex="_ba4341a4ab83ab70f1e0a755ee8fd8e8">
  61. <saml2:AuthnContext>
  62. <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
  63. </saml2:AuthnContext>
  64. </saml2:AuthnStatement>
  65. <saml2:AttributeStatement>
  66. <saml2:Attribute Name="companyId">
  67. <saml2:AttributeValue>CompanyID</saml2:AttributeValue>
  68. </saml2:Attribute>
  69. </saml2:AttributeStatement>
  70. </saml2:Assertion>
  71. </saml2p:Response>

站外资源

[1] SAML DEVELOPER TOOLS[EB/OL]. https://www.samltool.com/self_signed_certs.php
[2] OASIS标准组织对于 SAML 定义[EB/OL]. https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
[3] 联合登录概述[EB/OL]. https://help.aliyun.com/document_detail/93684.html?spm=a2c4g.11186623.6.572.320a4366SUrzHp