整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Authing Share|理解 SAML2 協議

          Authing Share|理解 SAML2 協議

          AML2 綜述

          安全斷言標記語言(英語:Security Assertion Markup Language,簡稱SAML,發音 sam-el)是一個基于 XML 的開源標準數據格式,它在當事方之間交換身份驗證和授權數據,尤其是在身份提供者和服務提供者之間交換。SAML2.0 可以實現基于網絡跨域的單點登錄(SSO), 以便于減少向一個用戶分發多個身份驗證令牌的管理開銷。


          SAML 主體

          在 SAML 協議中,涉及兩個主體:

          Service Provider 服務提供方,簡稱 SP。什么是服務提供方?例如:阿里云控制臺、騰訊云控制臺、AWS 控制臺這些都是服務提供方。

          Identity Provider 身份提供方,簡稱 IdP。什么是身份提供方?Authing 可以作為身份提供方,身份提供方能夠向 SP 發送身份斷言,所謂身份斷言就是由 Authing 簽發的,可以標識某個人身份的 Token,只不過,在 SAML 協議中,這個 Token 的格式是 XML 形式的。還有一些其他的身份提供方,例如 Okta、SSOCircle、Auth0,他們都可以向 SP 返回身份斷言。

          兩個主體通過用戶的瀏覽器進行信息交換。方式上,SP 可以返回帶參數的重定向 HTTP 響應,讓用戶立刻通過參數將信息發給 IdP。而 IdP 會返回一個表單,同時還有一段立即提交表單的 JS 代碼,從而讓用戶立刻將信息發給 SP。

          總結一下,SP 提供服務,需要知道用戶的身份,就需要向 IdP 詢問。IdP 知道用戶的身份,當用戶在 IdP 登錄成功,IdP 就將用戶的身份以 SAML 斷言的形式發給 SP。SP 信任 IdP 發來的身份斷言,從而賦予該用戶在 SP 的相關權限。


          SAML Request

          當用戶的身份無法鑒定時,SP 會向 IdP 發送 SAML Request 信息(通過瀏覽器發送),請求 IdP 來鑒定用戶身份。

          由阿里云控制臺發起一次 SAML Request 的形式是這樣的:

          GET https://core.authing.cn/v2/api/saml-idp/5e10927e4ecfd464fb4edaf6?SAMLRequest=fZJLT%2BMwFIX3%2FIrI%2B7yct9Wk6kyFQGJERQKL2RnnJnWV2Blfp2L%2BPaGlDLOApaV7vnN0jlfrl3FwjmBQalWS0AuIA0roVqq%2BJI%2FNtZuTdXW1Qj4OdGKb2e7VA%2FyZAa2zQQRjF91PrXAewdRgjlLA48NdSfbWTsh8H2WvpPL4IP%2FOyhN69N9Qfl3fE2e7UKTi9mR9EQhtwOOLz5LAE8o%2FUp9P8qRyZTv5CYRBQTOIQXRtnMbdcwwt71LiXGsj4JSwJB0fEIhzuy0Jp9AXgvaHgwzzPA%2FjfXagbRYlebeP%2BmI5wh1HlEf4J0Oc4Vah5cqWhAY0cIPCpXkTRiwoWJJ5eZH%2BJs7OaKuFHn5IdS5sNoppjhKZ4iMgs4LVm193jHoBez4fIbtpmp27u68b4jxdiqdvxS9TKGTnqr9nTe%2FGpDovw06JzWfC9wB%2B2Y5UXy8VRlmcpkWUpUlGY5p8TLfyP7tW78%2F%2Fv0f1Cg%3D%3D

          (提示:代碼可向右滑動)


          SAMLRequest 參數通過 query 在 URL 中發送給 IdP,SAMLRequest 的內容如下:

          fZJLT+MwFIX3/IrI+7yct9Wk6kyFQGJERQKL2RnnJnWV2Blfp2L+PaGlDLOApaV7vnN0jlfrl3FwjmBQalWS0AuIA0roVqq+JI/NtZuTdXW1Qj4OdGKb2e7VA/yZAa2zQQRjF91PrXAewdRgjlLA48NdSfbWTsh8H2WvpPL4IP/OyhN69N9Qfl3fE2e7UKTi9mR9EQhtwOOLz5LAE8o/Up9P8qRyZTv5CYRBQTOIQXRtnMbdcwwt71LiXGsj4JSwJB0fEIhzuy0Jp9AXgvaHgwzzPA/jfXagbRYlebeP+mI5wh1HlEf4J0Oc4Vah5cqWhAY0cIPCpXkTRiwoWJJ5eZH+Js7OaKuFHn5IdS5sNoppjhKZ4iMgs4LVm193jHoBez4fIbtpmp27u68b4jxdiqdvxS9TKGTnqr9nTe/GpDovw06JzWfC9wB+2Y5UXy8VRlmcpkWUpUlGY5p8TLfyP7tW78//v0f1Cg==

          (提示:代碼可向右滑動)


          base64 decode + inflate 解碼后(https://www.samltool.com/decode.php)

          <?xml version="1.0" encoding="UTF-8"?>
          <saml2p:AuthnRequest AssertionConsumerServiceURL="https://signin.aliyun.com/saml/SSO" Destination="https://core.authing.cn/v2/api/saml-idp/5e10927e4ecfd464fb4edaf6" ForceAuthn="false" ID="a2eg9c2gjji188814h7j2d7358fh3g9" IsPassive="false" IssueInstant="2020-09-28T13:09:57.896Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"
           xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
           <saml2:Issuer
            xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://signin.aliyun.com/1374669376572425/saml/SSO
           </saml2:Issuer>
          </saml2p:AuthnRequest>

          (提示:代碼可向右滑動)


          SAML Response

          IdP 收到 SAML Request 后,會彈出登錄框對用戶身份進行認證:

          當用戶在 IdP 完成登錄后,SAML IdP 將用戶身份斷言發送給 SP(放在表單中,通過瀏覽器 POST 請求發送)。SAML IdP 的響應內容如下:

          <form id="saml-form" method="post" action="https://signin.aliyun.com/saml/SSO" autocomplete="off">
            <input
              type="hidden"
              name="SAMLResponse"
              id="saml-response"
              value="PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfNjJiMTc3YzEtYTkxOS00MmY2LTk1ODYtNDdmMTNiNzEwODFmIiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMC0wOS0yOFQxMzozMDozMS43ODhaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zaWduaW4uYWxpeXVuLmNvbS9zYW1sL1NTTyIgSW5SZXNwb25zZVRvPSJhNDlmOGVkaTMxY2owYTJhNDU5ZzAzMzFjM2Q5YzEwIj4KICA8c2FtbDpJc3N1ZXI+aHR0cHM6Ly8yMG5xdWx2b3FwYnAuYXV0aGluZy5jbjwvc2FtbDpJc3N1ZXI+CiAgPHNhbWxwOlN0YXR1cz4KICAgIDxzYW1scDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz4KICA8L3NhbWxwOlN0YXR1cz4KICA8c2FtbDpBc3NlcnRpb24geG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBJRD0iX2ZhZTk1YjQ3LWNiZjMtNGEyMC1hZGQwLTk5ZDg1NmI0MTI0ZSIgVmVyc2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMjAtMDktMjhUMTM6MzA6MzEuNzg4WiI+CiAgICA8c2FtbDpJc3N1ZXI+aHR0cHM6Ly8yMG5xdWx2b3FwYnAuYXV0aGluZy5jbjwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3JzYS1zaGExIi8+PGRzOlJlZmVyZW5jZSBVUkk9IiNfZmFlOTViNDctY2JmMy00YTIwLWFkZDAtOTlkODU2YjQxMjRlIj48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjc2hhMSIvPjxkczpEaWdlc3RWYWx1ZT4vb2w2bEMxaitzbWRvbmw0OCtsSlR6VWVxbnc9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPmF3emNFMGRwOEJ6VFc0YjRQRmFSWDdOS09DOTViTHFPblBlQUtJL0NzRGZHYUpkbXpDSzBmVmxpeitlNlh6Qmx1S2ZCcFF0clFvbktsN2sydlZOYVBGeDlQcFNWendLOTFITEd2WVEwcUIzNnVBNEhGdm0vM00zMURMM1pSRlBScTY4WmFWQUc2bE1WZDBZYmlJblZ2OUZXd3NpKzZqRXBGK1BSbG1rb3FBST08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSUNRakNDQWF1Z0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRMEZBREErTVFzd0NRWURWUVFHRXdKMWN6RVNNQkFHQTFVRUNBd0o1THFMNWE2ZTVMaUtNUXd3Q2dZRFZRUUtEQU56YzNNeERUQUxCZ05WQkFNTUJITnpjM013SGhjTk1qQXdNVEF6TVRNeE9ERTBXaGNOTWpFd01UQXlNVE14T0RFMFdqQStNUXN3Q1FZRFZRUUdFd0oxY3pFU01CQUdBMVVFQ0F3SjVMcUw1YTZlNUxpS01Rd3dDZ1lEVlFRS0RBTnpjM014RFRBTEJnTlZCQU1NQkhOemMzTXdnWjh3RFFZSktvWklodmNOQVFFQkJRQURnWTBBTUlHSkFvR0JBTU5XbE1rNEwrVGNXd3lkOXBsVFBMaEhML1VNQ1BHSmd2NVZwOHZhQXA0V01zR3R3T0xJMVVOV2NjSXFNZVUwS2FzSnFyS3hIWXZxOUp6Wmg0ZmZ0Rm1vd0J6MzZ2ejBlSVVzUDVQS3ZGVUxrQzF2anJkbitRSlhiSjUxYWxaWktmUGdsMUhJOHc2bGgxMmFXVGphS1ErS2VtSXR0cUxxSmdMV09ZQVhQSXN6QWdNQkFBR2pVREJPTUIwR0ExVWREZ1FXQkJUVDEwNGhWWVZuUHBnN2FGckRpWFBTaGJ0eFVUQWZCZ05WSFNNRUdEQVdnQlRUMTA0aFZZVm5QcGc3YUZyRGlYUFNoYnR4VVRBTUJnTlZIUk1FQlRBREFRSC9NQTBHQ1NxR1NJYjNEUUVCRFFVQUE0R0JBQjYrMXhLN0dNSmE1TTZVamcvd2Q0RXR3eThOZFRGNnlwU3FOMzZCZDVPZFBtd1U5SHpEdUdqS2kzWndvb1BJR1JCOHBpTHNLazExTTRJaEFGNEMyUi9Kc3ZWWXdXT1lnb2pXNEgxaFI1d2syam43cGx0V3FSUGRmWkJsMFlmc0R5c1VQN2s4L01jaE9XWDdXaWZOeHBlM0dkU0tOMTdDa2RSakw5MjRiVjBsPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+CiAgICA8c2FtbDpTdWJqZWN0PgogICAgICA8c2FtbDpOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDp1bnNwZWNpZmllZCI+eWV6dXdlaUBhdXRoaW5nLm9uYWxpeXVuLmNvbTwvc2FtbDpOYW1lSUQ+CiAgICAgIDxzYW1sOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj4KICAgICAgICA8c2FtbDpTdWJqZWN0Q29uZmlybWF0aW9uRGF0YSBOb3RPbk9yQWZ0ZXI9IjIwMjAtMDktMjhUMTQ6MzA6MzEuNzg4WiIgUmVjaXBpZW50PSJodHRwczovL3NpZ25pbi5hbGl5dW4uY29tL3NhbWwvU1NPIiBJblJlc3BvbnNlVG89ImE0OWY4ZWRpMzFjajBhMmE0NTlnMDMzMWMzZDljMTAiLz4KICAgICAgPC9zYW1sOlN1YmplY3RDb25maXJtYXRpb24+CiAgICA8L3NhbWw6U3ViamVjdD4KICAgIDxzYW1sOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIwLTA5LTI4VDEzOjMwOjMxLjc4OFoiIE5vdE9uT3JBZnRlcj0iMjAyMC0wOS0yOFQxNDozMDozMS43ODhaIj4KICAgICAgPHNhbWw6QXVkaWVuY2VSZXN0cmljdGlvbj4KICAgICAgICA8c2FtbDpBdWRpZW5jZT5odHRwczovL3NpZ25pbi5hbGl5dW4uY29tLzEzNzQ2NjkzNzY1NzI0MjUvc2FtbC9TU088L3NhbWw6QXVkaWVuY2U+CiAgICAgIDwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPgogICAgPC9zYW1sOkNvbmRpdGlvbnM+PHNhbWw6QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDIwLTA5LTI4VDEzOjMwOjMxLjg4OFoiIFNlc3Npb25JbmRleD0ib29ldW1jcTZlSGpkZHIxSDNGeXpvdTdDcy1PR1RzTmwiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3Nlczp1bnNwZWNpZmllZDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlIE5hbWU9ImVtYWlsIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPnllenV3ZWlAYXV0aGluZy5jbjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJuYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OmJhc2ljIj48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEiIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciLz48L3NhbWw6QXR0cmlidXRlPjxzYW1sOkF0dHJpYnV0ZSBOYW1lPSJ1c2VybmFtZSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hIiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj55ZXp1d2VpQGF1dGhpbmcuY248L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0icGhvbmUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+bnVsbDwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48L3NhbWw6QXR0cmlidXRlPjwvc2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PC9zYW1sOkFzc2VydGlvbj4KPC9zYW1scDpSZXNwb25zZT4="
            />
            <input
              type="hidden"
              name="RelayState"
              id="relay-state"
              value=""
            />
          </form>
          <script type="text/javascript">
            (function() {
              document.forms[0].submit();
            })();
          </script>

          (提示:代碼可向右滑動)

          沒有什么神秘的,就是一個 HTML form 表單和一段立即提交該表單的 JS 代碼。其中的 SAML Response 信息如下:


          base64 decode + inflate 解碼后

          (https://www.samltool.com/decode.php)

          <samlp:Response
           xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
           xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_62b177c1-a919-42f6-9586-47f13b71081f" Version="2.0" IssueInstant="2020-09-28T13:30:31.788Z" Destination="https://signin.aliyun.com/saml/SSO" InResponseTo="a49f8edi31cj0a2a459g0331c3d9c10">
           <saml:Issuer>https://20nqulvoqpbp.authing.cn</saml:Issuer>
           <samlp:Status>
            <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
           </samlp:Status>
           <saml:Assertion
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_fae95b47-cbf3-4a20-add0-99d856b4124e" Version="2.0" IssueInstant="2020-09-28T13:30:31.788Z">
            <saml:Issuer>https://20nqulvoqpbp.authing.cn</saml:Issuer>
            <ds:Signature
             xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
             <ds:SignedInfo>
              <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
              <ds:Reference URI="#_fae95b47-cbf3-4a20-add0-99d856b4124e">
               <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/2000/09/xmldsig#sha1"/>
               <ds:DigestValue>/ol6lC1j+smdonl48+lJTzUeqnw=</ds:DigestValue>
              </ds:Reference>
             </ds:SignedInfo>
             <ds:SignatureValue>awzcE0dp8BzTW4b4PFaRX7NKOC95bLqOnPeAKI/CsDfGaJdmzCK0fVliz+e6XzBluKfBpQtrQonKl7k2vVNaPFx9PpSVzwK91HLGvYQ0qB36uA4HFvm/3M31DL3ZRFPRq68ZaVAG6lMVd0YbiInVv9FWwsi+6jEpF+PRlmkoqAI=</ds:SignatureValue>
             <ds:KeyInfo>
              <ds:X509Data>
               <ds:X509Certificate>MIICQjCCAaugAwIBAgIBADANBgkqhkiG9w0BAQ0FADA+MQswCQYDVQQGEwJ1czESMBAGA1UECAwJ5LqL5a6e5LiKMQwwCgYDVQQKDANzc3MxDTALBgNVBAMMBHNzc3MwHhcNMjAwMTAzMTMxODE0WhcNMjEwMTAyMTMxODE0WjA+MQswCQYDVQQGEwJ1czESMBAGA1UECAwJ5LqL5a6e5LiKMQwwCgYDVQQKDANzc3MxDTALBgNVBAMMBHNzc3MwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMNWlMk4L+TcWwyd9plTPLhHL/UMCPGJgv5Vp8vaAp4WMsGtwOLI1UNWccIqMeU0KasJqrKxHYvq9JzZh4fftFmowBz36vz0eIUsP5PKvFULkC1vjrdn+QJXbJ51alZZKfPgl1HI8w6lh12aWTjaKQ+KemIttqLqJgLWOYAXPIszAgMBAAGjUDBOMB0GA1UdDgQWBBTT104hVYVnPpg7aFrDiXPShbtxUTAfBgNVHSMEGDAWgBTT104hVYVnPpg7aFrDiXPShbtxUTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAB6+1xK7GMJa5M6Ujg/wd4Etwy8NdTF6ypSqN36Bd5OdPmwU9HzDuGjKi3ZwooPIGRB8piLsKk11M4IhAF4C2R/JsvVYwWOYgojW4H1hR5wk2jn7pltWqRPdfZBl0YfsDysUP7k8/MchOWX7WifNxpe3GdSKN17CkdRjL924bV0l</ds:X509Certificate>
              </ds:X509Data>
             </ds:KeyInfo>
            </ds:Signature>
            <saml:Subject>
             <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">yezuwei@authing.onaliyun.com</saml:NameID>
             <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
              <saml:SubjectConfirmationData NotOnOrAfter="2020-09-28T14:30:31.788Z" Recipient="https://signin.aliyun.com/saml/SSO" InResponseTo="a49f8edi31cj0a2a459g0331c3d9c10"/>
             </saml:SubjectConfirmation>
            </saml:Subject>
            <saml:Conditions NotBefore="2020-09-28T13:30:31.788Z" NotOnOrAfter="2020-09-28T14:30:31.788Z">
             <saml:AudienceRestriction>
              <saml:Audience>https://signin.aliyun.com/1374669376572425/saml/SSO</saml:Audience>
             </saml:AudienceRestriction>
            </saml:Conditions>
            <saml:AuthnStatement AuthnInstant="2020-09-28T13:30:31.888Z" SessionIndex="ooeumcq6eHjddr1H3Fyzou7Cs-OGTsNl">
             <saml:AuthnContext>
              <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
             </saml:AuthnContext>
            </saml:AuthnStatement>
            <saml:AttributeStatement>
             <saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
              <saml:AttributeValue
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">yezuwei@authing.cn
              </saml:AttributeValue>
             </saml:Attribute>
             <saml:Attribute Name="name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
              <saml:AttributeValue
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string"/>
              </saml:Attribute>
              <saml:Attribute Name="username" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
               <saml:AttributeValue
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">yezuwei@authing.cn
               </saml:AttributeValue>
              </saml:Attribute>
              <saml:Attribute Name="phone" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
               <saml:AttributeValue
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">null
               </saml:AttributeValue>
              </saml:Attribute>
             </saml:AttributeStatement>
            </saml:Assertion>
           </samlp:Response>

          (提示:代碼可向右滑動)


          這段內容就是用戶的身份斷言,也就是用戶的 Token,只不過這個 Token 通過 XML 格式傳遞。

          讀到這里,你可能會對 SP、IdP 如何處理這些冗長的 XML 信息感到困惑。Authing 會解決這些繁瑣的處理,而你只需關注如何正確地配置 Authing IdP,與 SAML SP 進行通信。


          SAML2 流程

          本文為讀者講述 SAML 中,SP、IdP、瀏覽器三個實體之間數據交互的流程。


          SAML 協議中涉及到的主體

          使用 SAML 協議進行身份認證時,涉及到以下三個主體

          • 瀏覽器:SP 和 IdP 借助瀏覽器互相通信
          • SP:資源提供方
          • IdP:身份認證提供方


          發起 SAML 登錄到登錄成功的整個過程

          1. 用戶試圖登錄 SP 提供的應用。
          2. SP 生成 SAML Request,通過瀏覽器重定向,向 IdP 發送 SAML Request。
          3. IdP 解析 SAML Request 并將用戶重定向到認證頁面。
          4. 用戶在認證頁面完成登錄。
          5. IdP 生成 SAML Response,通過對瀏覽器重定向,向 SP 的 ACS 地址返回 SAML Response,其中包含 SAML Assertion 用于確定用戶身份。
          6. SP 對 SAML Response 的內容進行檢驗。
          7. 用戶成功登錄到 SP 提供的應用。


          SP 與 IdP 之間通信方式

          SP 與 IdP 之間的通信方式分為 HTTP Redirect Binding、HTTP POST Binding、HTTP Artifact Binding。每種方式在不同的階段會用不同類型的 HTTP 與對方通信。


          HTTP Redirect Binding

          SP 通過重定向 GET 請求把 SAML Request 發送到 IdP,IdP 通過立即提交的 Form 表單以 POST 請求的方式將 SAML Response 發到 SP。


          HTTP POST Binding

          IdP 通過立即提交的 Form 表單以 POST 請求的方式將 SAML Request 發到 SP。IdP 通過立即提交的 Form 表單以 POST 請求的方式將 SAML Response 發到 SP。


          HTTP Artifact Binding

          SP、IdP 雙方只通過瀏覽器交換 SAML Request、SAML Response 的索引編號,收到編號后,在后端請求對方的 Artifact Resolution Service 接口來獲取真正的請求實體內容。從而避免 SAML Request、SAML Response 暴露在前端。

          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協議是怎么處理的。

          1. 用戶通過User Agent請求Service Provider,比如:
          http://sp.flydean.com/myresource
          

          SP將會對該資源進行相應的安全檢查,如果發現已經有一個有效的安全上下文的話,SP將會跳過2-7步,直接進入第8步。

          1. 如果在第一步的時候,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
              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來進行簽名。

          1. User agent將會發送一個get請求到IdP的SSO server :
          GET /SAML2/SSO/Redirect?SAMLRequest=request&RelayState=token HTTP/1.1
          Host: idp.flydean.com
          

          IdP收到這個AuthnRequest請求之后,將會進行安全驗證,如果是合法的AuthnRequest,那么將會展示登錄界面。

          1. 用戶可以輸入用戶名密碼進行登錄。登錄成功之后,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
              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信息。

          1. user agent 收到XHTML form之后將會提交該form給SP。
          2. SP中的assertion consumer service將會處理這個請求,創建相關的安全上下文,并將user agent重定向到要訪問的資源頁面。
          3. user agent再次請求SP資源。
          4. 因為安全上下文已經創建完畢,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的博客

          歡迎關注我的公眾號:「程序那些事」最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!


          主站蜘蛛池模板: 亚洲视频在线观看一区| 相泽亚洲一区中文字幕| 国产激情з∠视频一区二区 | 亚洲av区一区二区三| 午夜福利av无码一区二区| 国产精品区AV一区二区| 暖暖免费高清日本一区二区三区| 美女视频在线一区二区三区| 中文字幕在线播放一区| 日本丰满少妇一区二区三区| 国产一区二区三区不卡在线看 | 日韩一区二区在线视频| 无码免费一区二区三区免费播放 | 亚洲福利电影一区二区?| 亚洲线精品一区二区三区| 中文字幕日韩人妻不卡一区 | 日本美女一区二区三区| 成人无码精品一区二区三区| 国产精品制服丝袜一区| 无码国产精品一区二区免费| 91精品福利一区二区| 亚洲欧美国产国产一区二区三区 | 色系一区二区三区四区五区| 精品国产免费观看一区| 日韩高清一区二区三区不卡| 无码一区二区三区亚洲人妻| 视频一区二区在线观看| 亚洲av区一区二区三| 久久国产精品一区二区| 免费无码毛片一区二区APP| 亚洲一区欧洲一区| 日韩精品一区二区三区在线观看l| 精品免费国产一区二区| 一区二区三区福利| 秋霞午夜一区二区| 无码人妻aⅴ一区二区三区| 狠狠爱无码一区二区三区| 一本大道东京热无码一区| 3d动漫精品成人一区二区三| 精品国产一区二区三区免费看 | 中文字幕一区二区三区精华液 |