作者:Longofo@知道創宇404實驗室
日期:2022年11月8日

SAML始于2001年,最終的SAML 2.0版本發布于2005年,此后也沒有發布大版本,SAML 2.0一直延續到了現在。SAML已經是老古董了,現在SSO里面使用更多的是OAuth。在某些漏洞平臺看到過一些SAML漏洞報告,一些大型應用依然出現過它的身影,最近看到的一個議題《Hacking the Cloud With SAML》[1]也提到了,考考古學學也不虧,至少它的一些概念現在仍在延用。

SAML 2.0

SAML: Security Assertion Markup Language,一種用于安全性斷言標記的語言。

SAML的用途:

  • 單點登錄(SSO Single Sign-ON)
  • 聯合認證(Federated Identity)
  • 在其他架構內使用SAML,例如WS-Security

后續的內容主要是SAML SSO的部分。

SAML協議中的三方:瀏覽器,身份鑒別服務器(IDP,Identity Provider),服務提供者(SP,Service provider),以及這三方相互的通訊次序,加密方法,傳輸數據格式。

可能大家在網絡上看到的一些流程圖會多一兩個步驟或少一兩個步驟,那只是開發人員在具體選擇和實現SAML傳輸時存在的一些差異,對于我們了解整個SAML認證流程問題不大,知一反三就行。基本的認證流程如下:

圖先大概瀏覽下,后續會在OpenSAML的案例中看到每個環節的細節。

通過OpenSAML請求包看SAML SSO

OpenSAML是SAML協議的一個開源實現,在github找了一個用OpenSAML實現的SSO demo,使用的是HTTP-POST傳輸SAML,有幾百個star。將項目跑起來,正常的登錄一遍看下完整的通信包過程,9090端口是SP,8080端口是IDP

用戶訪問SP服務

request:

GET /user.html?force-authn=true HTTP/1.1
Host: 192.168.0.104:9090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:9090/
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaSpSessionId=2E15F753B56E4646FA4CACCE4DD2ED6D; mujinaIdpSessionId=6203026E878EFB44F90769F285FB05D9
Connection: close

response:

HTTP/1.1 200 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Content-Language: zh-CN
Date: Sat, 22 Oct 2022 10:29:57 GMT
Connection: close
Content-Length: 889

<!DOCTYPE html>
<html>
<head>
    <title>Mujina Service Provider</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="/main.css"/>
    <script src="/sp.js"></script>
</head>
<body>
<section class="login-container-wrapper">
    <section class="login-container">
        <section class="login">
            <h1>Mujina Service Provider</h1>
            <a id="user-link" class="button" href="/user.html?force-authn=false">Login</a>
            <section class="force-authn">
                <input type="checkbox" id="force-authn" name="force-authn"/>
                <label for="force-authn">Force Authn request?</label>
            </section>
        </section>
        <a class="powered-by" href="https://openconext.org/" target="_blank">Copyright ?? 2018 OpenConext</a>
    </section>
</section>
</body>
</html>

返回SP登錄頁,用戶點擊登錄。

SP返回重定向

request:

GET /user.html?force-authn=true HTTP/1.1
Host: 192.168.0.104:9090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:9090/
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaSpSessionId=2E15F753B56E4646FA4CACCE4DD2ED6D; mujinaIdpSessionId=6203026E878EFB44F90769F285FB05D9
Connection: close

response:

HTTP/1.1 200 
Set-Cookie: mujinaSpSessionId=F6BCE4D93AA256056960B9459E27B374; Path=/; HttpOnly
Cache-control: no-cache, no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Date: Sat, 22 Oct 2022 10:30:02 GMT
Connection: close
Content-Length: 4483


<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
    </head>
    <body onload="document.forms[0].submit()">
        <noscript>
            <p>
                <strong>Note:</strong> Since your browser does not support JavaScript,
                you must press the Continue button once to proceed.
            </p>
        </noscript>

        <form action="http&#x3a;&#x2f;&#x2f;192.168.0.104&#x3a;8080&#x2f;SingleSignOnService" method="post">
            <div>

<input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwOi8vMTkyLjE2OC4wLjEwNDo5MDkwL3NhbWwvU1NPIiBEZXN0aW5hdGlvbj0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6ODA4MC9TaW5nbGVTaWduT25TZXJ2aWNlIiBGb3JjZUF1dGhuPSJ0cnVlIiBJRD0iYWhnZzRhNDVkZWg5aTY3aDBmMmllZGdhMDc1NWciIElzUGFzc2l2ZT0iZmFsc2UiIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDowMi4xMTVaIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLVBPU1QiIFZlcnNpb249IjIuMCI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI+aHR0cDovL21vY2stc3A8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+PGRzOlJlZmVyZW5jZSBVUkk9IiNhaGdnNGE0NWRlaDlpNjdoMGYyaWVkZ2EwNzU1ZyI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8+PGRzOkRpZ2VzdFZhbHVlPlc0dGxMc3RsVWQ3Rk9zU25JNFBtTVMwMFhybTFQQmExRDExNU03RkRxbkk9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8+PGRzOlNpZ25hdHVyZVZhbHVlPm9lOGQzQTZMVU1Wd05FUmd4UHIwdEl1Uk9vKzBSdzV6MTJuOTlQSnhKS05XYXZlVEdiZkFBMVBNRTQ5NFQyalZnNUhtTmVLUHJDQk1Ubk93RGZpcm16VFNDc3hUT3F3aFpJMXNOcW5rSXNMSnljenVGUjUyWUVMbVpMbms5NzQzeWVRRDBkSndLR1lRR0JCcklEOEFKdWhvQUtIWU83NFkvYWJlZDBWYTZrdmV2ZjR2a3RxY1A0R1lhc2M2MW44ajhTc2VHZ0M0a1RYdE9wdWg2UFpnLzdlZlJlNndpT3JVNDZodjdRRVpQbjZKc09mbDZxSjd0TWVjZUV6b05zTnVvcjRidjZVV05ZemlPN3U3SmkzTkdOWnQ0RXdtekNTR1dxcWdoTE5XLzVZd2FwWnpxc0ppaTBYMHEvZnZSMXFkNVQwSmpheHZpZUtZS2tmTGV0SHhiZz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlERXpDQ0FmdWdBd0lCQWdJSkFLb0svaGVCamNPWU1BMEdDU3FHU0liM0RRRUJCUVVBTUNBeEhqQWNCZ05WQkFvTUZVOXlaMkZ1DQphWHBoZEdsdmJpd2dRMDQ5VDBsRVF6QWVGdzB4TlRFeE1URXhNREV5TVRWYUZ3MHlOVEV4TVRBeE1ERXlNVFZhTUNBeEhqQWNCZ05WDQpCQW9NRlU5eVoyRnVhWHBoZEdsdmJpd2dRMDQ5VDBsRVF6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCDQpBTkJHd0ovcXBUUU5pU2dVZ2xTRTJVekVrVW93K3dTOHI2N2V0eG9FaGx6SlpmZ0svazVUZkcxd0lDRHFhcEhBeEVWZ1VNMTBhQkhSDQpjdE5vY0E1d21sSHR4ZGlkaHpSWnJvcUh3cEt5MkJtc0tYNVoyb0syNVJMcHN5dXNCMUtyb2VtZ0EvQ2pVbkk2cklMMXh4Rm4zS3lPDQpGaDFaQkxVUXRLTlFlTVM3SEZHZ1NEQXArc1h1VEZ1anoxMkxGRHVnWDBUMEtCNWExKzBsOHkwUEVhMHlHYTFvaTZzZU9OeDg0OVpIDQp4TTBQUnZVdW5Xa3VUTStmb1owalpwRmFwWGUwMnlXTXFoYy8yaVlNaWVFLzNHdk9ndUpjaEp0NlIrY3V0OFZCYjZ1YktVSUdLN3BtDQpvcS9UQjZEVlhwdnNIcXNESlhlY2h4Y2ljdTRwZEtWREhTZWM4NTBDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRks3UnFqb29kU1lWDQpYR1RWRWRMZjNrSmZsUC9zTUI4R0ExVWRJd1FZTUJhQUZLN1Jxam9vZFNZVlhHVFZFZExmM2tKZmxQL3NNQXdHQTFVZEV3UUZNQU1CDQpBZjh3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUROWmt4bEZYaDRGNDVtdUNiblFkK1dtYVhsR3ZiOXRrVXlBSXhWTDhBSXU4SjE4DQpGNDIwdnBuR3BvVUFFK0h5M2V2Qm1wMm5rckZBZ21yMDU1ZkFqcEhlWkZnRFpCQVBDd1lkM1ROTURlU3lNdGEzS2Erb1M3R1JGRGVQDQprTUVtK2tINC9ySVROS1VGMXNPdldCVFNvd2s5VHVkRUR5RnFnR250Y2R1L2wvelJ4dngzM3kzTE1HNVVTRDB4NFg0SUtqUnJSTjFCDQpiY0tnaThkcTEwQzNqZHFOYW5jVHVQb3FUM1dXelJ2VnRCL3EzNEI3Rjc0LzZKemdFb09DRUh1ZkJNcDRaRnU1NFAweUVHdFdmVHdUDQp6dW9ab2JyQ2hWVkJ0NHcvWFphZ3JSdFVDRE53UnBITmJwanhZdWRicUxxcGkxTVFwVjlvaHQvQnBUSFZKRzJpMHJvPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE+PC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4="/>                

            </div>
            <noscript>
                <div>
                    <input type="submit" value="Continue"/>
                </div>
            </noscript>
        </form>
    </body>
</html>

返回了IDP登錄URL,并附帶了AuthnRequest,這里base64編碼了,解開并格式化之后如下:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest
    xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://192.168.0.104:9090/saml/SSO" Destination="http://192.168.0.104:8080/SingleSignOnService" ForceAuthn="true" ID="ahgg4a45deh9i67h0f2iedga0755g" IsPassive="false" IssueInstant="2022-10-22T10:30:02.115Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
    <saml2:Issuer
        xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://mock-sp
    </saml2: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/2001/04/xmldsig-more#rsa-sha256"/>
            <ds:Reference URI="#ahgg4a45deh9i67h0f2iedga0755g">
                <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>W4tlLstlUd7FOsSnI4PmMS00Xrm1PBa1D115M7FDqnI=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>oe8d3A6LUMVwNERgxPr0tIuROo+0Rw5z12n99PJxJKNWaveTGbfAA1PME494T2jVg5HmNeKPrCBMTnOwDfirmzTSCsxTOqwhZI1sNqnkIsLJyczuFR52YELmZLnk9743yeQD0dJwKGYQGBBrID8AJuhoAKHYO74Y/abed0Va6kvevf4vktqcP4GYasc61n8j8SseGgC4kTXtOpuh6PZg/7efRe6wiOrU46hv7QEZPn6JsOfl6qJ7tMeceEzoNsNuor4bv6UWNYziO7u7Ji3NGNZt4EwmzCSGWqqghLNW/5YwapZzqsJii0X0q/fvR1qd5T0JjaxvieKYKkfLetHxbg==</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIIDEzCCAfugAwIBAgIJAKoK/heBjcOYMA0GCSqGSIb3DQEBBQUAMCAxHjAcBgNVBAoMFU9yZ2Fu
aXphdGlvbiwgQ049T0lEQzAeFw0xNTExMTExMDEyMTVaFw0yNTExMTAxMDEyMTVaMCAxHjAcBgNV
BAoMFU9yZ2FuaXphdGlvbiwgQ049T0lEQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
ANBGwJ/qpTQNiSgUglSE2UzEkUow+wS8r67etxoEhlzJZfgK/k5TfG1wICDqapHAxEVgUM10aBHR
ctNocA5wmlHtxdidhzRZroqHwpKy2BmsKX5Z2oK25RLpsyusB1KroemgA/CjUnI6rIL1xxFn3KyO
Fh1ZBLUQtKNQeMS7HFGgSDAp+sXuTFujz12LFDugX0T0KB5a1+0l8y0PEa0yGa1oi6seONx849ZH
xM0PRvUunWkuTM+foZ0jZpFapXe02yWMqhc/2iYMieE/3GvOguJchJt6R+cut8VBb6ubKUIGK7pm
oq/TB6DVXpvsHqsDJXechxcicu4pdKVDHSec850CAwEAAaNQME4wHQYDVR0OBBYEFK7RqjoodSYV
XGTVEdLf3kJflP/sMB8GA1UdIwQYMBaAFK7RqjoodSYVXGTVEdLf3kJflP/sMAwGA1UdEwQFMAMB
Af8wDQYJKoZIhvcNAQEFBQADggEBADNZkxlFXh4F45muCbnQd+WmaXlGvb9tkUyAIxVL8AIu8J18
F420vpnGpoUAE+Hy3evBmp2nkrFAgmr055fAjpHeZFgDZBAPCwYd3TNMDeSyMta3Ka+oS7GRFDeP
kMEm+kH4/rITNKUF1sOvWBTSowk9TudEDyFqgGntcdu/l/zRxvx33y3LMG5USD0x4X4IKjRrRN1B
bcKgi8dq10C3jdqNancTuPoqT3WWzRvVtB/q34B7F74/6JzgEoOCEHufBMp4ZFu54P0yEGtWfTwT
zuoZobrChVVBt4w/XZagrRtUCDNwRpHNbpjxYudbqLqpi1MQpV9oht/BpTHVJG2i0ro=</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
</saml2p:AuthnRequest>

挨個看下每個標簽和屬性的含義。

AuthnRequest

SP向IDP傳達我想認證一個用戶,這里面不包含用戶信息,里面包含的是SP的基本信息。

  • AssertionConsumerServiceURL: 指定IDP認證成功之后,要將AuthnResponse發送到SP的哪個URL處理
  • Destination: 指定IDP認證的端點
  • ForceAuthn: 強制認證,就算之前認證過,瀏覽器攜帶了認證的session,如果這個值為true,還是會重新認證
  • ID: 隨機標識,主要是用來方便在其他標簽引用,例如在SignedInfo中的Reference
  • IsPassive: 默認為 false 。如果為 true,則IdP不能顯示的通過瀏覽器與用戶進行交互,用戶不能感知到跳轉的存在
  • IssueInstant: 請求的簽發時間
  • ProtocolBinding: 使用什么來傳輸SAML消息,這里是通過HTTP POST來傳輸
  • Version: 2.0版本

Issuer

用于標識AuthnRequest請求消息的實際簽發者,通常情況下也是 URI格式。

Signature

簽名方式,這里使用的是xmldsig(XML Signature),這是一個概念不是指具體的算法,具體的算法在SignedInfo中。

SignedInfo

  • CanonicalizationMethod: 規范化算法,作用對象是Signature標簽里面的內容,這里用的xml-exc-c14n,是一種用來規范xml格式的算法
  • SignatureMethod: 用什么方法對DigestValue簽名,注意這里簽名的對象是摘要值而不是xml對象,摘要對象才是xml
  • Reference: 引用,這里引用的ID就是AuthnRequest里面的ID,表示Refernece里面其他標簽信息都會作用到AuthnRequest標簽以及子標簽里的內容
  • Transforms: 可以指定多個transform,對引用對象進行鏈式處理,比如enveloped-signature是采用部分簽名方式,即AuthnRequest中的Signature標簽在計算摘要時是不會計入到摘要內容;xml-exc-c14n算法是對AuthnRequest里面的內容進行規范化處理
  • DigestMethod: 對AuthnRequest信息的摘要算法,sha256類似md5算法,單向算法,不可逆,采用這種方式進行摘要計算
  • DigestValue: 對AuthnRequest信息的摘要值

SignatureValue

簽名結果,這里簽名對象是SignedInfo標簽。

KeyInfo

包含了X509公鑰證書信息,X509Certificate里面的公鑰會被用于摘要,IDP收到AuthnRequest后,也會用這個公鑰來解密簽名信息,然后和摘要值對比,看信息是否被篡改。

如何摘要,摘的是哪部分,簽的是哪部分,后續分析代碼細節會看到。

瀏覽器重定向到IDP

request:

POST /SingleSignOnService HTTP/1.1
Host: 192.168.0.104:8080
Content-Length: 3718
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.104:9090
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:9090/
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaIdpSessionId=6203026E878EFB44F90769F285FB05D9; mujinaSpSessionId=F6BCE4D93AA256056960B9459E27B374
Connection: close

SAMLRequest=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwOi8vMTkyLjE2OC4wLjEwNDo5MDkwL3NhbWwvU1NPIiBEZXN0aW5hdGlvbj0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6ODA4MC9TaW5nbGVTaWduT25TZXJ2aWNlIiBGb3JjZUF1dGhuPSJ0cnVlIiBJRD0iYWhnZzRhNDVkZWg5aTY3aDBmMmllZGdhMDc1NWciIElzUGFzc2l2ZT0iZmFsc2UiIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDowMi4xMTVaIiBQcm90b2NvbEJpbmRpbmc9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpiaW5kaW5nczpIVFRQLVBPU1QiIFZlcnNpb249IjIuMCI%2BPHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiI%2BaHR0cDovL21vY2stc3A8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8%2BPGRzOlJlZmVyZW5jZSBVUkk9IiNhaGdnNGE0NWRlaDlpNjdoMGYyaWVkZ2EwNzU1ZyI%2BPGRzOlRyYW5zZm9ybXM%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHM6VHJhbnNmb3Jtcz48ZHM6RGlnZXN0TWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxlbmMjc2hhMjU2Ii8%2BPGRzOkRpZ2VzdFZhbHVlPlc0dGxMc3RsVWQ3Rk9zU25JNFBtTVMwMFhybTFQQmExRDExNU03RkRxbkk9PC9kczpEaWdlc3RWYWx1ZT48L2RzOlJlZmVyZW5jZT48L2RzOlNpZ25lZEluZm8%2BPGRzOlNpZ25hdHVyZVZhbHVlPm9lOGQzQTZMVU1Wd05FUmd4UHIwdEl1Uk9vKzBSdzV6MTJuOTlQSnhKS05XYXZlVEdiZkFBMVBNRTQ5NFQyalZnNUhtTmVLUHJDQk1Ubk93RGZpcm16VFNDc3hUT3F3aFpJMXNOcW5rSXNMSnljenVGUjUyWUVMbVpMbms5NzQzeWVRRDBkSndLR1lRR0JCcklEOEFKdWhvQUtIWU83NFkvYWJlZDBWYTZrdmV2ZjR2a3RxY1A0R1lhc2M2MW44ajhTc2VHZ0M0a1RYdE9wdWg2UFpnLzdlZlJlNndpT3JVNDZodjdRRVpQbjZKc09mbDZxSjd0TWVjZUV6b05zTnVvcjRidjZVV05ZemlPN3U3SmkzTkdOWnQ0RXdtekNTR1dxcWdoTE5XLzVZd2FwWnpxc0ppaTBYMHEvZnZSMXFkNVQwSmpheHZpZUtZS2tmTGV0SHhiZz09PC9kczpTaWduYXR1cmVWYWx1ZT48ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE%2BPGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlERXpDQ0FmdWdBd0lCQWdJSkFLb0svaGVCamNPWU1BMEdDU3FHU0liM0RRRUJCUVVBTUNBeEhqQWNCZ05WQkFvTUZVOXlaMkZ1DQphWHBoZEdsdmJpd2dRMDQ5VDBsRVF6QWVGdzB4TlRFeE1URXhNREV5TVRWYUZ3MHlOVEV4TVRBeE1ERXlNVFZhTUNBeEhqQWNCZ05WDQpCQW9NRlU5eVoyRnVhWHBoZEdsdmJpd2dRMDQ5VDBsRVF6Q0NBU0l3RFFZSktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCDQpBTkJHd0ovcXBUUU5pU2dVZ2xTRTJVekVrVW93K3dTOHI2N2V0eG9FaGx6SlpmZ0svazVUZkcxd0lDRHFhcEhBeEVWZ1VNMTBhQkhSDQpjdE5vY0E1d21sSHR4ZGlkaHpSWnJvcUh3cEt5MkJtc0tYNVoyb0syNVJMcHN5dXNCMUtyb2VtZ0EvQ2pVbkk2cklMMXh4Rm4zS3lPDQpGaDFaQkxVUXRLTlFlTVM3SEZHZ1NEQXArc1h1VEZ1anoxMkxGRHVnWDBUMEtCNWExKzBsOHkwUEVhMHlHYTFvaTZzZU9OeDg0OVpIDQp4TTBQUnZVdW5Xa3VUTStmb1owalpwRmFwWGUwMnlXTXFoYy8yaVlNaWVFLzNHdk9ndUpjaEp0NlIrY3V0OFZCYjZ1YktVSUdLN3BtDQpvcS9UQjZEVlhwdnNIcXNESlhlY2h4Y2ljdTRwZEtWREhTZWM4NTBDQXdFQUFhTlFNRTR3SFFZRFZSME9CQllFRks3UnFqb29kU1lWDQpYR1RWRWRMZjNrSmZsUC9zTUI4R0ExVWRJd1FZTUJhQUZLN1Jxam9vZFNZVlhHVFZFZExmM2tKZmxQL3NNQXdHQTFVZEV3UUZNQU1CDQpBZjh3RFFZSktvWklodmNOQVFFRkJRQURnZ0VCQUROWmt4bEZYaDRGNDVtdUNiblFkK1dtYVhsR3ZiOXRrVXlBSXhWTDhBSXU4SjE4DQpGNDIwdnBuR3BvVUFFK0h5M2V2Qm1wMm5rckZBZ21yMDU1ZkFqcEhlWkZnRFpCQVBDd1lkM1ROTURlU3lNdGEzS2Erb1M3R1JGRGVQDQprTUVtK2tINC9ySVROS1VGMXNPdldCVFNvd2s5VHVkRUR5RnFnR250Y2R1L2wvelJ4dngzM3kzTE1HNVVTRDB4NFg0SUtqUnJSTjFCDQpiY0tnaThkcTEwQzNqZHFOYW5jVHVQb3FUM1dXelJ2VnRCL3EzNEI3Rjc0LzZKemdFb09DRUh1ZkJNcDRaRnU1NFAweUVHdFdmVHdUDQp6dW9ab2JyQ2hWVkJ0NHcvWFphZ3JSdFVDRE53UnBITmJwanhZdWRicUxxcGkxTVFwVjlvaHQvQnBUSFZKRzJpMHJvPTwvZHM6WDUwOUNlcnRpZmljYXRlPjwvZHM6WDUwOURhdGE%2BPC9kczpLZXlJbmZvPjwvZHM6U2lnbmF0dXJlPjwvc2FtbDJwOkF1dGhuUmVxdWVzdD4%3D

response:

HTTP/1.1 302 
Set-Cookie: mujinaIdpSessionId=C54BBCAED0850B9E50195AD02DEAA9D6; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://192.168.0.104:8080/login
Content-Length: 0
Date: Sat, 22 Oct 2022 10:30:02 GMT
Connection: close

這里IDP會驗證AuthnRequest信息是否正確,然后將用戶重定向到IDP的登錄頁。

IDP返回登錄頁

省點篇幅,這里的請求和響應信息就不貼了,對流程的熟悉沒影響。

用戶輸入賬號密碼登錄

request:

POST /login HTTP/1.1
Host: 192.168.0.104:8080
Content-Length: 118
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.104:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:8080/login
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaSpSessionId=F6BCE4D93AA256056960B9459E27B374; mujinaIdpSessionId=C54BBCAED0850B9E50195AD02DEAA9D6
Connection: close

username=wewe&password=ererer&persist-me=on&urn%3Amace%3Aterena.org%3Aattribute-def%3AschacHomeOrganizationType=ererer

response:

HTTP/1.1 302 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://192.168.0.104:8080/SingleSignOnService
Content-Length: 0
Date: Sat, 22 Oct 2022 10:30:12 GMT
Connection: close

IDP對校驗用戶,用戶認證成功,生成AuthnResponse緩存到session中,然后重定向到SingleSignOnService,后面瀏覽器會使用GET在請求一次SingleSignOnService端點。

瀏覽器重定向到SingleSignOnService

request:

GET /SingleSignOnService HTTP/1.1
Host: 192.168.0.104:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:8080/login
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaSpSessionId=F6BCE4D93AA256056960B9459E27B374; mujinaIdpSessionId=C54BBCAED0850B9E50195AD02DEAA9D6
Connection: close

response:

HTTP/1.1 200 
Cache-control: no-cache, no-store
Pragma: no-cache
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Type: text/html;charset=UTF-8
Date: Sat, 22 Oct 2022 10:30:12 GMT
Connection: close
Content-Length: 13542


<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
    </head>
    <body onload="document.forms[0].submit()">
        <noscript>
            <p>
                <strong>Note:</strong> Since your browser does not support JavaScript,
                you must press the Continue button once to proceed.
            </p>
        </noscript>

        <form action="http&#x3a;&#x2f;&#x2f;192.168.0.104&#x3a;9090&#x2f;saml&#x2f;SSO" method="post">
            <div>


<input type="hidden" name="SAMLResponse" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6OTA5MC9zYW1sL1NTTyIgSUQ9Il9jNTBjMjQzZi1hNjA2LTRhNDMtOTQ4Ni1lYWVjMTUyYzJjMTEiIEluUmVzcG9uc2VUbz0iYWhnZzRhNDVkZWg5aTY3aDBmMmllZGdhMDc1NWciIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDRaIiBWZXJzaW9uPSIyLjAiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI+PHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHA6Ly9tb2NrLWlkcDwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI19jNTBjMjQzZi1hNjA2LTRhNDMtOTQ4Ni1lYWVjMTUyYzJjMTEiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjxlYzpJbmNsdXNpdmVOYW1lc3BhY2VzIHhtbG5zOmVjPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiIFByZWZpeExpc3Q9InhzIi8+PC9kczpUcmFuc2Zvcm0+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU+ZjRCVEU3SDFRUkJPbUMxblJwbXcwc09GZ0RrK3VMZ0c3cS9jTWhraUQ1bz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+TWUwMU9VYW01bGVKRjR3U1BlTTNxK0IrbUttd0pSVUxhT1k3OWhYd3hxVWJEUG13bFNKYisxdFoxK25ZdGlOVUVrWXVkUFhaT2tmOFNkbFVoRFVLSUx2dHdmb2dYVEpsZXRXd05WTzB5NmhLSFhxbW5TYXpLWmVSK3RrMWJEYTUvSnQyR0l3WlFOZkEzYUUxQlJOaUplZEpCTHc5MUFPMDJuZ0VuUlhWY3RWdFU0WHdIbHJYYlRVYWNkNDQraERyV0JvblFid1JmMEZxUll2ZTNCNEp5dWJKUDAya2ZnL3RIYTlUN1dPc0MvaE9oS2crVzZURzMySzgwbXRCeFk1MEI1RkFoSGpZRDVZcURaN0ZVL2dOQXl5cGo4VVhsTTBvdDduNm9xL1h2Y3VZTDkvMEMwemUzVS92ZXNOczhMQzFqN3lDa1JReXhBbHlsSUhSYnY4QWt3PT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURFekNDQWZ1Z0F3SUJBZ0lKQUtvSy9oZUJqY09ZTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ0F4SGpBY0JnTlZCQW9NRlU5eVoyRnUNCmFYcGhkR2x2Yml3Z1EwNDlUMGxFUXpBZUZ3MHhOVEV4TVRFeE1ERXlNVFZhRncweU5URXhNVEF4TURFeU1UVmFNQ0F4SGpBY0JnTlYNCkJBb01GVTl5WjJGdWFYcGhkR2x2Yml3Z1EwNDlUMGxFUXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUINCkFOQkd3Si9xcFRRTmlTZ1VnbFNFMlV6RWtVb3crd1M4cjY3ZXR4b0VobHpKWmZnSy9rNVRmRzF3SUNEcWFwSEF4RVZnVU0xMGFCSFINCmN0Tm9jQTV3bWxIdHhkaWRoelJacm9xSHdwS3kyQm1zS1g1WjJvSzI1Ukxwc3l1c0IxS3JvZW1nQS9DalVuSTZySUwxeHhGbjNLeU8NCkZoMVpCTFVRdEtOUWVNUzdIRkdnU0RBcCtzWHVURnVqejEyTEZEdWdYMFQwS0I1YTErMGw4eTBQRWEweUdhMW9pNnNlT054ODQ5WkgNCnhNMFBSdlV1bldrdVRNK2ZvWjBqWnBGYXBYZTAyeVdNcWhjLzJpWU1pZUUvM0d2T2d1SmNoSnQ2UitjdXQ4VkJiNnViS1VJR0s3cG0NCm9xL1RCNkRWWHB2c0hxc0RKWGVjaHhjaWN1NHBkS1ZESFNlYzg1MENBd0VBQWFOUU1FNHdIUVlEVlIwT0JCWUVGSzdScWpvb2RTWVYNClhHVFZFZExmM2tKZmxQL3NNQjhHQTFVZEl3UVlNQmFBRks3UnFqb29kU1lWWEdUVkVkTGYza0pmbFAvc01Bd0dBMVVkRXdRRk1BTUINCkFmOHdEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRE5aa3hsRlhoNEY0NW11Q2JuUWQrV21hWGxHdmI5dGtVeUFJeFZMOEFJdThKMTgNCkY0MjB2cG5HcG9VQUUrSHkzZXZCbXAybmtyRkFnbXIwNTVmQWpwSGVaRmdEWkJBUEN3WWQzVE5NRGVTeU10YTNLYStvUzdHUkZEZVANCmtNRW0ra0g0L3JJVE5LVUYxc092V0JUU293azlUdWRFRHlGcWdHbnRjZHUvbC96Unh2eDMzeTNMTUc1VVNEMHg0WDRJS2pSclJOMUINCmJjS2dpOGRxMTBDM2pkcU5hbmNUdVBvcVQzV1d6UnZWdEIvcTM0QjdGNzQvNkp6Z0VvT0NFSHVmQk1wNFpGdTU0UDB5RUd0V2ZUd1QNCnp1b1pvYnJDaFZWQnQ0dy9YWmFnclJ0VUNETndScEhOYnBqeFl1ZGJxTHFwaTFNUXBWOW9odC9CcFRIVkpHMmkwcm89PC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWwycDpTdGF0dXM+PHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM+PHNhbWwyOkFzc2VydGlvbiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9iM2E5MjEzMy1jMTkwLTQ5NzItODkxOC1kNmE1OGE3NWFiYjQiIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDlaIiBWZXJzaW9uPSIyLjAiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI+PHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI+aHR0cDovL21vY2staWRwPC9zYW1sMjpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjX2IzYTkyMTMzLWMxOTAtNDk3Mi04OTE4LWQ2YTU4YTc1YWJiNCI+PGRzOlRyYW5zZm9ybXM+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8+PGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI+PGVjOkluY2x1c2l2ZU5hbWVzcGFjZXMgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgUHJlZml4TGlzdD0ieHMiLz48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT51UWpWVCt0MTQySUluVVdIY1BkTmthMnhQNDYrZ1VOeCtXMGxmenMyZkI4PTwvZHM6RGlnZXN0VmFsdWU+PC9kczpSZWZlcmVuY2U+PC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5kb3NVZVorLzcvc0c0bWJXR1htVVc2eWkyaGx6eDAwUkVtVmQxdHZuSWptMTBkYnpJdnpmakpHVzN5WjhGUFc2VmovWkNXL2JtWlkvdktTT08zVDNTMlhDUGlLUEVSUzVaLzRMSUxoMmhFa1dTSUdlaFhUZm1EeHdzQ255RE9LMUVqeTdFeGp0OFRiTVdpRDlwRFFLWGlHeWtYbnJvYThJK0tJOU1ITUtkUDEzU2x4WnVIRDkzbG13bWFwWGF4NmN3NFptOE1CMXY5Q0RnVWZGUlY0amFndlRZTnFyS1Z0N2VtQmJuYzJ4eFF0aWFMZDNxNk5OUWdVWE5BUzVXMUJvUVJKd0wzQ2pKNzJzUFRZUXhPSGRxcWNMUU5qTW5wUlg3UmRxODBlOGRkejYza2ZWa2wwVXBSaW9ZS1FURnA4UzZlMnIxQ29JT2pNMHBhM2hlTmtSc3c9PTwvZHM6U2lnbmF0dXJlVmFsdWU+PC9kczpTaWduYXR1cmU+PHNhbWwyOlN1YmplY3Q+PHNhbWwyOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OnVuc3BlY2lmaWVkIj53ZXdlPC9zYW1sMjpOYW1lSUQ+PHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJhaGdnNGE0NWRlaDlpNjdoMGYyaWVkZ2EwNzU1ZyIgTm90T25PckFmdGVyPSIyMDIyLTEwLTIyVDE4OjMwOjEyLjU0NloiIFJlY2lwaWVudD0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6OTA5MC9zYW1sL1NTTyIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q+PHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIyLTEwLTIyVDEwOjI3OjEyLjU0NloiIE5vdE9uT3JBZnRlcj0iMjAyMi0xMC0yMlQxMDozMzoxMi41NDZaIj48c2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDI6QXVkaWVuY2U+aHR0cDovL21vY2stc3A8L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM+PHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDdaIj48c2FtbDI6QXV0aG5Db250ZXh0PjxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY+PHNhbWwyOkF1dGhlbnRpY2F0aW5nQXV0aG9yaXR5Pmh0dHA6Ly9tb2NrLWlkcDwvc2FtbDI6QXV0aGVudGljYXRpbmdBdXRob3JpdHk+PC9zYW1sMjpBdXRobkNvbnRleHQ+PC9zYW1sMjpBdXRoblN0YXRlbWVudD48c2FtbDI6QXR0cmlidXRlU3RhdGVtZW50PjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6ZGlzcGxheU5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+Sm9obiBEb2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6dWlkIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPndld2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6Y24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+Sm9obiBEb2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6c24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+RG9lPC9zYW1sMjpBdHRyaWJ1dGVWYWx1ZT48L3NhbWwyOkF0dHJpYnV0ZT48c2FtbDI6QXR0cmlidXRlIE5hbWU9InVybjptYWNlOmRpcjphdHRyaWJ1dGUtZGVmOmVkdVBlcnNvblByaW5jaXBhbE5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI+ai5kb2VAZXhhbXBsZS5jb208L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6Z2l2ZW5OYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI+PHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPkpvaG48L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6bWFpbCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5qLmRvZUBleGFtcGxlLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PHNhbWwyOkF0dHJpYnV0ZSBOYW1lPSJ1cm46bWFjZTp0ZXJlbmEub3JnOmF0dHJpYnV0ZS1kZWY6c2NoYWNIb21lT3JnYW5pemF0aW9uVHlwZSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5lcmVyZXI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6dGVyZW5hLm9yZzphdHRyaWJ1dGUtZGVmOnNjaGFjSG9tZU9yZ2FuaXphdGlvbiIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5leGFtcGxlLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU+PC9zYW1sMjpBdHRyaWJ1dGU+PC9zYW1sMjpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PC9zYW1sMjpBc3NlcnRpb24+PC9zYW1sMnA6UmVzcG9uc2U+"/>                
<input type="hidden" name="Signature" value="LeMNm3aevRONrMuFm9o9GJvkF/fe3KdO9j7cU9bMS0YB5IxYzo7uSE6Kgt7dLkUC41puWhTg8lP861HqeAPUhwvoRIvRxac2aa3euPpOz+vcWepAkYTQuVxznH5gn24qYRIiBflWlVgcw7iGUHeCPP2Gk9Pf5pFaGnFeSc2CR47in1sq0tp1qTUSWTdADPV4S/K5njRLFXBYcO9YwHafFjVlEtMgeWyUxPpSBFuClpVfF8T91O3X43Q444yP4tJz7cEntI6FzRCH62N1lvz0bXz3Z6JKQ9G8MfOwvGNAIfC72cwCWyewUPRzrFR4Gw7ZV4ZYSLcMlVpGxKmxVv7o0A=="/>                
<input type="hidden" name="SigAlg" value="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>                
<input type="hidden" name="KeyInfo" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48ZHM6S2V5SW5mbyB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+PGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU+TUlJREV6Q0NBZnVnQXdJQkFnSUpBS29LL2hlQmpjT1lNQTBHQ1NxR1NJYjNEUUVCQlFVQU1DQXhIakFjQmdOVkJBb01GVTl5WjJGdQ0KYVhwaGRHbHZiaXdnUTA0OVQwbEVRekFlRncweE5URXhNVEV4TURFeU1UVmFGdzB5TlRFeE1UQXhNREV5TVRWYU1DQXhIakFjQmdOVg0KQkFvTUZVOXlaMkZ1YVhwaGRHbHZiaXdnUTA0OVQwbEVRekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQg0KQU5CR3dKL3FwVFFOaVNnVWdsU0UyVXpFa1Vvdyt3UzhyNjdldHhvRWhsekpaZmdLL2s1VGZHMXdJQ0RxYXBIQXhFVmdVTTEwYUJIUg0KY3ROb2NBNXdtbEh0eGRpZGh6Ulpyb3FId3BLeTJCbXNLWDVaMm9LMjVSTHBzeXVzQjFLcm9lbWdBL0NqVW5JNnJJTDF4eEZuM0t5Tw0KRmgxWkJMVVF0S05RZU1TN0hGR2dTREFwK3NYdVRGdWp6MTJMRkR1Z1gwVDBLQjVhMSswbDh5MFBFYTB5R2Exb2k2c2VPTng4NDlaSA0KeE0wUFJ2VXVuV2t1VE0rZm9aMGpacEZhcFhlMDJ5V01xaGMvMmlZTWllRS8zR3ZPZ3VKY2hKdDZSK2N1dDhWQmI2dWJLVUlHSzdwbQ0Kb3EvVEI2RFZYcHZzSHFzREpYZWNoeGNpY3U0cGRLVkRIU2VjODUwQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZLN1Jxam9vZFNZVg0KWEdUVkVkTGYza0pmbFAvc01COEdBMVVkSXdRWU1CYUFGSzdScWpvb2RTWVZYR1RWRWRMZjNrSmZsUC9zTUF3R0ExVWRFd1FGTUFNQg0KQWY4d0RRWUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFETlpreGxGWGg0RjQ1bXVDYm5RZCtXbWFYbEd2Yjl0a1V5QUl4Vkw4QUl1OEoxOA0KRjQyMHZwbkdwb1VBRStIeTNldkJtcDJua3JGQWdtcjA1NWZBanBIZVpGZ0RaQkFQQ3dZZDNUTk1EZVN5TXRhM0thK29TN0dSRkRlUA0Ka01FbStrSDQvcklUTktVRjFzT3ZXQlRTb3drOVR1ZEVEeUZxZ0dudGNkdS9sL3pSeHZ4MzN5M0xNRzVVU0QweDRYNElLalJyUk4xQg0KYmNLZ2k4ZHExMEMzamRxTmFuY1R1UG9xVDNXV3pSdlZ0Qi9xMzRCN0Y3NC82SnpnRW9PQ0VIdWZCTXA0WkZ1NTRQMHlFR3RXZlR3VA0KenVvWm9ickNoVlZCdDR3L1haYWdyUnRVQ0ROd1JwSE5icGp4WXVkYnFMcXBpMU1RcFY5b2h0L0JwVEhWSkcyaTBybz08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz4="/>                
            </div>
            <noscript>
                <div>
                    <input type="submit" value="Continue"/>
                </div>
            </noscript>
        </form>

    </body>
</html>

響應中,IDP返回了AuthnResponse內容,還有其他兩個參數。

瀏覽器重定向到SP

request:

POST /saml/SSO HTTP/1.1
Host: 192.168.0.104:9090
Content-Length: 12712
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://192.168.0.104:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.0.104:8080/
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,vi;q=0.7
Cookie: mujinaSpSessionId=F6BCE4D93AA256056960B9459E27B374; mujinaIdpSessionId=C54BBCAED0850B9E50195AD02DEAA9D6
Connection: close

SAMLResponse=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOlJlc3BvbnNlIHhtbG5zOnNhbWwycD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBEZXN0aW5hdGlvbj0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6OTA5MC9zYW1sL1NTTyIgSUQ9Il9jNTBjMjQzZi1hNjA2LTRhNDMtOTQ4Ni1lYWVjMTUyYzJjMTEiIEluUmVzcG9uc2VUbz0iYWhnZzRhNDVkZWg5aTY3aDBmMmllZGdhMDc1NWciIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDRaIiBWZXJzaW9uPSIyLjAiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI%2BPHNhbWwyOklzc3VlciB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6bmFtZWlkLWZvcm1hdDplbnRpdHkiPmh0dHA6Ly9tb2NrLWlkcDwvc2FtbDI6SXNzdWVyPjxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxkczpTaWduZWRJbmZvPjxkczpDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8%2BPGRzOlNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48ZHM6UmVmZXJlbmNlIFVSST0iI19jNTBjMjQzZi1hNjA2LTRhNDMtOTQ4Ni1lYWVjMTUyYzJjMTEiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiPjxlYzpJbmNsdXNpdmVOYW1lc3BhY2VzIHhtbG5zOmVjPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiIFByZWZpeExpc3Q9InhzIi8%2BPC9kczpUcmFuc2Zvcm0%2BPC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU%2BZjRCVEU3SDFRUkJPbUMxblJwbXcwc09GZ0RrK3VMZ0c3cS9jTWhraUQ1bz08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU%2BTWUwMU9VYW01bGVKRjR3U1BlTTNxK0IrbUttd0pSVUxhT1k3OWhYd3hxVWJEUG13bFNKYisxdFoxK25ZdGlOVUVrWXVkUFhaT2tmOFNkbFVoRFVLSUx2dHdmb2dYVEpsZXRXd05WTzB5NmhLSFhxbW5TYXpLWmVSK3RrMWJEYTUvSnQyR0l3WlFOZkEzYUUxQlJOaUplZEpCTHc5MUFPMDJuZ0VuUlhWY3RWdFU0WHdIbHJYYlRVYWNkNDQraERyV0JvblFid1JmMEZxUll2ZTNCNEp5dWJKUDAya2ZnL3RIYTlUN1dPc0MvaE9oS2crVzZURzMySzgwbXRCeFk1MEI1RkFoSGpZRDVZcURaN0ZVL2dOQXl5cGo4VVhsTTBvdDduNm9xL1h2Y3VZTDkvMEMwemUzVS92ZXNOczhMQzFqN3lDa1JReXhBbHlsSUhSYnY4QWt3PT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURFekNDQWZ1Z0F3SUJBZ0lKQUtvSy9oZUJqY09ZTUEwR0NTcUdTSWIzRFFFQkJRVUFNQ0F4SGpBY0JnTlZCQW9NRlU5eVoyRnUNCmFYcGhkR2x2Yml3Z1EwNDlUMGxFUXpBZUZ3MHhOVEV4TVRFeE1ERXlNVFZhRncweU5URXhNVEF4TURFeU1UVmFNQ0F4SGpBY0JnTlYNCkJBb01GVTl5WjJGdWFYcGhkR2x2Yml3Z1EwNDlUMGxFUXpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUINCkFOQkd3Si9xcFRRTmlTZ1VnbFNFMlV6RWtVb3crd1M4cjY3ZXR4b0VobHpKWmZnSy9rNVRmRzF3SUNEcWFwSEF4RVZnVU0xMGFCSFINCmN0Tm9jQTV3bWxIdHhkaWRoelJacm9xSHdwS3kyQm1zS1g1WjJvSzI1Ukxwc3l1c0IxS3JvZW1nQS9DalVuSTZySUwxeHhGbjNLeU8NCkZoMVpCTFVRdEtOUWVNUzdIRkdnU0RBcCtzWHVURnVqejEyTEZEdWdYMFQwS0I1YTErMGw4eTBQRWEweUdhMW9pNnNlT054ODQ5WkgNCnhNMFBSdlV1bldrdVRNK2ZvWjBqWnBGYXBYZTAyeVdNcWhjLzJpWU1pZUUvM0d2T2d1SmNoSnQ2UitjdXQ4VkJiNnViS1VJR0s3cG0NCm9xL1RCNkRWWHB2c0hxc0RKWGVjaHhjaWN1NHBkS1ZESFNlYzg1MENBd0VBQWFOUU1FNHdIUVlEVlIwT0JCWUVGSzdScWpvb2RTWVYNClhHVFZFZExmM2tKZmxQL3NNQjhHQTFVZEl3UVlNQmFBRks3UnFqb29kU1lWWEdUVkVkTGYza0pmbFAvc01Bd0dBMVVkRXdRRk1BTUINCkFmOHdEUVlKS29aSWh2Y05BUUVGQlFBRGdnRUJBRE5aa3hsRlhoNEY0NW11Q2JuUWQrV21hWGxHdmI5dGtVeUFJeFZMOEFJdThKMTgNCkY0MjB2cG5HcG9VQUUrSHkzZXZCbXAybmtyRkFnbXIwNTVmQWpwSGVaRmdEWkJBUEN3WWQzVE5NRGVTeU10YTNLYStvUzdHUkZEZVANCmtNRW0ra0g0L3JJVE5LVUYxc092V0JUU293azlUdWRFRHlGcWdHbnRjZHUvbC96Unh2eDMzeTNMTUc1VVNEMHg0WDRJS2pSclJOMUINCmJjS2dpOGRxMTBDM2pkcU5hbmNUdVBvcVQzV1d6UnZWdEIvcTM0QjdGNzQvNkp6Z0VvT0NFSHVmQk1wNFpGdTU0UDB5RUd0V2ZUd1QNCnp1b1pvYnJDaFZWQnQ0dy9YWmFnclJ0VUNETndScEhOYnBqeFl1ZGJxTHFwaTFNUXBWOW9odC9CcFRIVkpHMmkwcm89PC9kczpYNTA5Q2VydGlmaWNhdGU%2BPC9kczpYNTA5RGF0YT48L2RzOktleUluZm8%2BPC9kczpTaWduYXR1cmU%2BPHNhbWwycDpTdGF0dXM%2BPHNhbWwycDpTdGF0dXNDb2RlIFZhbHVlPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6c3RhdHVzOlN1Y2Nlc3MiLz48L3NhbWwycDpTdGF0dXM%2BPHNhbWwyOkFzc2VydGlvbiB4bWxuczpzYW1sMj0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9iM2E5MjEzMy1jMTkwLTQ5NzItODkxOC1kNmE1OGE3NWFiYjQiIElzc3VlSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDlaIiBWZXJzaW9uPSIyLjAiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSI%2BPHNhbWwyOklzc3VlciBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OmVudGl0eSI%2BaHR0cDovL21vY2staWRwPC9zYW1sMjpJc3N1ZXI%2BPGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlNpZ25lZEluZm8%2BPGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHM6U2lnbmF0dXJlTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8wNC94bWxkc2lnLW1vcmUjcnNhLXNoYTI1NiIvPjxkczpSZWZlcmVuY2UgVVJJPSIjX2IzYTkyMTMzLWMxOTAtNDk3Mi04OTE4LWQ2YTU4YTc1YWJiNCI%2BPGRzOlRyYW5zZm9ybXM%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNlbnZlbG9wZWQtc2lnbmF0dXJlIi8%2BPGRzOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyI%2BPGVjOkluY2x1c2l2ZU5hbWVzcGFjZXMgeG1sbnM6ZWM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIgUHJlZml4TGlzdD0ieHMiLz48L2RzOlRyYW5zZm9ybT48L2RzOlRyYW5zZm9ybXM%2BPGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkczpEaWdlc3RWYWx1ZT51UWpWVCt0MTQySUluVVdIY1BkTmthMnhQNDYrZ1VOeCtXMGxmenMyZkI4PTwvZHM6RGlnZXN0VmFsdWU%2BPC9kczpSZWZlcmVuY2U%2BPC9kczpTaWduZWRJbmZvPjxkczpTaWduYXR1cmVWYWx1ZT5kb3NVZVorLzcvc0c0bWJXR1htVVc2eWkyaGx6eDAwUkVtVmQxdHZuSWptMTBkYnpJdnpmakpHVzN5WjhGUFc2VmovWkNXL2JtWlkvdktTT08zVDNTMlhDUGlLUEVSUzVaLzRMSUxoMmhFa1dTSUdlaFhUZm1EeHdzQ255RE9LMUVqeTdFeGp0OFRiTVdpRDlwRFFLWGlHeWtYbnJvYThJK0tJOU1ITUtkUDEzU2x4WnVIRDkzbG13bWFwWGF4NmN3NFptOE1CMXY5Q0RnVWZGUlY0amFndlRZTnFyS1Z0N2VtQmJuYzJ4eFF0aWFMZDNxNk5OUWdVWE5BUzVXMUJvUVJKd0wzQ2pKNzJzUFRZUXhPSGRxcWNMUU5qTW5wUlg3UmRxODBlOGRkejYza2ZWa2wwVXBSaW9ZS1FURnA4UzZlMnIxQ29JT2pNMHBhM2hlTmtSc3c9PTwvZHM6U2lnbmF0dXJlVmFsdWU%2BPC9kczpTaWduYXR1cmU%2BPHNhbWwyOlN1YmplY3Q%2BPHNhbWwyOk5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OnVuc3BlY2lmaWVkIj53ZXdlPC9zYW1sMjpOYW1lSUQ%2BPHNhbWwyOlN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48c2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJhaGdnNGE0NWRlaDlpNjdoMGYyaWVkZ2EwNzU1ZyIgTm90T25PckFmdGVyPSIyMDIyLTEwLTIyVDE4OjMwOjEyLjU0NloiIFJlY2lwaWVudD0iaHR0cDovLzE5Mi4xNjguMC4xMDQ6OTA5MC9zYW1sL1NTTyIvPjwvc2FtbDI6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWwyOlN1YmplY3Q%2BPHNhbWwyOkNvbmRpdGlvbnMgTm90QmVmb3JlPSIyMDIyLTEwLTIyVDEwOjI3OjEyLjU0NloiIE5vdE9uT3JBZnRlcj0iMjAyMi0xMC0yMlQxMDozMzoxMi41NDZaIj48c2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48c2FtbDI6QXVkaWVuY2U%2BaHR0cDovL21vY2stc3A8L3NhbWwyOkF1ZGllbmNlPjwvc2FtbDI6QXVkaWVuY2VSZXN0cmljdGlvbj48L3NhbWwyOkNvbmRpdGlvbnM%2BPHNhbWwyOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMi0xMC0yMlQxMDozMDoxMi41NDdaIj48c2FtbDI6QXV0aG5Db250ZXh0PjxzYW1sMjpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZDwvc2FtbDI6QXV0aG5Db250ZXh0Q2xhc3NSZWY%2BPHNhbWwyOkF1dGhlbnRpY2F0aW5nQXV0aG9yaXR5Pmh0dHA6Ly9tb2NrLWlkcDwvc2FtbDI6QXV0aGVudGljYXRpbmdBdXRob3JpdHk%2BPC9zYW1sMjpBdXRobkNvbnRleHQ%2BPC9zYW1sMjpBdXRoblN0YXRlbWVudD48c2FtbDI6QXR0cmlidXRlU3RhdGVtZW50PjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6ZGlzcGxheU5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2BSm9obiBEb2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6dWlkIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI%2BPHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPndld2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6Y24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2BSm9obiBEb2U8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6c24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2BRG9lPC9zYW1sMjpBdHRyaWJ1dGVWYWx1ZT48L3NhbWwyOkF0dHJpYnV0ZT48c2FtbDI6QXR0cmlidXRlIE5hbWU9InVybjptYWNlOmRpcjphdHRyaWJ1dGUtZGVmOmVkdVBlcnNvblByaW5jaXBhbE5hbWUiIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6dXJpIj48c2FtbDI6QXR0cmlidXRlVmFsdWUgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnR5cGU9InhzOnN0cmluZyI%2Bai5kb2VAZXhhbXBsZS5jb208L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6Z2l2ZW5OYW1lIiBOYW1lRm9ybWF0PSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXR0cm5hbWUtZm9ybWF0OnVyaSI%2BPHNhbWwyOkF0dHJpYnV0ZVZhbHVlIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhzaTp0eXBlPSJ4czpzdHJpbmciPkpvaG48L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6ZGlyOmF0dHJpYnV0ZS1kZWY6bWFpbCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5qLmRvZUBleGFtcGxlLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU%2BPC9zYW1sMjpBdHRyaWJ1dGU%2BPHNhbWwyOkF0dHJpYnV0ZSBOYW1lPSJ1cm46bWFjZTp0ZXJlbmEub3JnOmF0dHJpYnV0ZS1kZWY6c2NoYWNIb21lT3JnYW5pemF0aW9uVHlwZSIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5lcmVyZXI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjxzYW1sMjpBdHRyaWJ1dGUgTmFtZT0idXJuOm1hY2U6dGVyZW5hLm9yZzphdHRyaWJ1dGUtZGVmOnNjaGFjSG9tZU9yZ2FuaXphdGlvbiIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDp1cmkiPjxzYW1sMjpBdHRyaWJ1dGVWYWx1ZSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiB4c2k6dHlwZT0ieHM6c3RyaW5nIj5leGFtcGxlLmNvbTwvc2FtbDI6QXR0cmlidXRlVmFsdWU%2BPC9zYW1sMjpBdHRyaWJ1dGU%2BPC9zYW1sMjpBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPC9zYW1sMjpBc3NlcnRpb24%2BPC9zYW1sMnA6UmVzcG9uc2U%2B&Signature=LeMNm3aevRONrMuFm9o9GJvkF%2Ffe3KdO9j7cU9bMS0YB5IxYzo7uSE6Kgt7dLkUC41puWhTg8lP861HqeAPUhwvoRIvRxac2aa3euPpOz%2BvcWepAkYTQuVxznH5gn24qYRIiBflWlVgcw7iGUHeCPP2Gk9Pf5pFaGnFeSc2CR47in1sq0tp1qTUSWTdADPV4S%2FK5njRLFXBYcO9YwHafFjVlEtMgeWyUxPpSBFuClpVfF8T91O3X43Q444yP4tJz7cEntI6FzRCH62N1lvz0bXz3Z6JKQ9G8MfOwvGNAIfC72cwCWyewUPRzrFR4Gw7ZV4ZYSLcMlVpGxKmxVv7o0A%3D%3D&SigAlg=http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmldsig-more%23rsa-sha256&KeyInfo=PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48ZHM6S2V5SW5mbyB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI%2BPGRzOlg1MDlEYXRhPjxkczpYNTA5Q2VydGlmaWNhdGU%2BTUlJREV6Q0NBZnVnQXdJQkFnSUpBS29LL2hlQmpjT1lNQTBHQ1NxR1NJYjNEUUVCQlFVQU1DQXhIakFjQmdOVkJBb01GVTl5WjJGdQ0KYVhwaGRHbHZiaXdnUTA0OVQwbEVRekFlRncweE5URXhNVEV4TURFeU1UVmFGdzB5TlRFeE1UQXhNREV5TVRWYU1DQXhIakFjQmdOVg0KQkFvTUZVOXlaMkZ1YVhwaGRHbHZiaXdnUTA0OVQwbEVRekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQg0KQU5CR3dKL3FwVFFOaVNnVWdsU0UyVXpFa1Vvdyt3UzhyNjdldHhvRWhsekpaZmdLL2s1VGZHMXdJQ0RxYXBIQXhFVmdVTTEwYUJIUg0KY3ROb2NBNXdtbEh0eGRpZGh6Ulpyb3FId3BLeTJCbXNLWDVaMm9LMjVSTHBzeXVzQjFLcm9lbWdBL0NqVW5JNnJJTDF4eEZuM0t5Tw0KRmgxWkJMVVF0S05RZU1TN0hGR2dTREFwK3NYdVRGdWp6MTJMRkR1Z1gwVDBLQjVhMSswbDh5MFBFYTB5R2Exb2k2c2VPTng4NDlaSA0KeE0wUFJ2VXVuV2t1VE0rZm9aMGpacEZhcFhlMDJ5V01xaGMvMmlZTWllRS8zR3ZPZ3VKY2hKdDZSK2N1dDhWQmI2dWJLVUlHSzdwbQ0Kb3EvVEI2RFZYcHZzSHFzREpYZWNoeGNpY3U0cGRLVkRIU2VjODUwQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZLN1Jxam9vZFNZVg0KWEdUVkVkTGYza0pmbFAvc01COEdBMVVkSXdRWU1CYUFGSzdScWpvb2RTWVZYR1RWRWRMZjNrSmZsUC9zTUF3R0ExVWRFd1FGTUFNQg0KQWY4d0RRWUpLb1pJaHZjTkFRRUZCUUFEZ2dFQkFETlpreGxGWGg0RjQ1bXVDYm5RZCtXbWFYbEd2Yjl0a1V5QUl4Vkw4QUl1OEoxOA0KRjQyMHZwbkdwb1VBRStIeTNldkJtcDJua3JGQWdtcjA1NWZBanBIZVpGZ0RaQkFQQ3dZZDNUTk1EZVN5TXRhM0thK29TN0dSRkRlUA0Ka01FbStrSDQvcklUTktVRjFzT3ZXQlRTb3drOVR1ZEVEeUZxZ0dudGNkdS9sL3pSeHZ4MzN5M0xNRzVVU0QweDRYNElLalJyUk4xQg0KYmNLZ2k4ZHExMEMzamRxTmFuY1R1UG9xVDNXV3pSdlZ0Qi9xMzRCN0Y3NC82SnpnRW9PQ0VIdWZCTXA0WkZ1NTRQMHlFR3RXZlR3VA0KenVvWm9ickNoVlZCdDR3L1haYWdyUnRVQ0ROd1JwSE5icGp4WXVkYnFMcXBpMU1RcFY5b2h0L0JwVEhWSkcyaTBybz08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz4%3D

response:

HTTP/1.1 302 
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Location: http://192.168.0.104:9090/user.html?force-authn=true
Content-Length: 0
Date: Sat, 22 Oct 2022 10:30:12 GMT
Connection: close

這一步一共發送了三個參數:

  • SAMLResponse: IDP認證用戶成功之后發送給SP的響應內容
  • SigAlg: 簽名算法,這里是用HTTP-POST來傳輸數據內容,為了保證接收到的數據沒有被修改過,對SAMLResponse這一堆字符串進行的簽名
  • KeyInfo: IDP的公鑰,IDP使用自己的私鑰對SAMLResponse那一堆字符串簽名,然后將自己的公鑰傳輸過去

當SP校驗AuthnResponse成功時,會正常顯示訪問的服務。這里看下AuthnResponse解碼并格式化后的內容:

<?xml version="1.0" encoding="utf-8"?>

<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="http://192.168.0.104:9090/saml/SSO" ID="_c50c243f-a606-4a43-9486-eaec152c2c11" InResponseTo="ahgg4a45deh9i67h0f2iedga0755g" IssueInstant="2022-10-22T10:30:12.544Z" Version="2.0">
  <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://mock-idp</saml2: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/2001/04/xmldsig-more#rsa-sha256"/>
      <ds:Reference URI="#_c50c243f-a606-4a43-9486-eaec152c2c11">
        <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#">
            <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"></ec:InclusiveNamespaces>
          </ds:Transform>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue>f4BTE7H1QRBOmC1nRpmw0sOFgDk+uLgG7q/cMhkiD5o=</ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>Me01OUam5leJF4wSPeM3q+B+mKmwJRULaOY79hXwxqUbDPmwlSJb+1tZ1+nYtiNUEkYudPXZOkf8SdlUhDUKILvtwfogXTJletWwNVO0y6hKHXqmnSazKZeR+tk1bDa5/Jt2GIwZQNfA3aE1BRNiJedJBLw91AO02ngEnRXVctVtU4XwHlrXbTUacd44+hDrWBonQbwRf0FqRYve3B4JyubJP02kfg/tHa9T7WOsC/hOhKg+W6TG32K80mtBxY50B5FAhHjYD5YqDZ7FU/gNAyypj8UXlM0ot7n6oq/XvcuYL9/0C0ze3U/vesNs8LC1j7yCkRQyxAlylIHRbv8Akw==</ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>MIIDEzCCAfugAwIBAgIJAKoK/heBjcOYMA0GCSqGSIb3DQEBBQUAMCAxHjAcBgNVBAoMFU9yZ2Fu aXphdGlvbiwgQ049T0lEQzAeFw0xNTExMTExMDEyMTVaFw0yNTExMTAxMDEyMTVaMCAxHjAcBgNV BAoMFU9yZ2FuaXphdGlvbiwgQ049T0lEQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANBGwJ/qpTQNiSgUglSE2UzEkUow+wS8r67etxoEhlzJZfgK/k5TfG1wICDqapHAxEVgUM10aBHR ctNocA5wmlHtxdidhzRZroqHwpKy2BmsKX5Z2oK25RLpsyusB1KroemgA/CjUnI6rIL1xxFn3KyO Fh1ZBLUQtKNQeMS7HFGgSDAp+sXuTFujz12LFDugX0T0KB5a1+0l8y0PEa0yGa1oi6seONx849ZH xM0PRvUunWkuTM+foZ0jZpFapXe02yWMqhc/2iYMieE/3GvOguJchJt6R+cut8VBb6ubKUIGK7pm oq/TB6DVXpvsHqsDJXechxcicu4pdKVDHSec850CAwEAAaNQME4wHQYDVR0OBBYEFK7RqjoodSYV XGTVEdLf3kJflP/sMB8GA1UdIwQYMBaAFK7RqjoodSYVXGTVEdLf3kJflP/sMAwGA1UdEwQFMAMB Af8wDQYJKoZIhvcNAQEFBQADggEBADNZkxlFXh4F45muCbnQd+WmaXlGvb9tkUyAIxVL8AIu8J18 F420vpnGpoUAE+Hy3evBmp2nkrFAgmr055fAjpHeZFgDZBAPCwYd3TNMDeSyMta3Ka+oS7GRFDeP kMEm+kH4/rITNKUF1sOvWBTSowk9TudEDyFqgGntcdu/l/zRxvx33y3LMG5USD0x4X4IKjRrRN1B bcKgi8dq10C3jdqNancTuPoqT3WWzRvVtB/q34B7F74/6JzgEoOCEHufBMp4ZFu54P0yEGtWfTwT zuoZobrChVVBt4w/XZagrRtUCDNwRpHNbpjxYudbqLqpi1MQpV9oht/BpTHVJG2i0ro=</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 xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_b3a92133-c190-4972-8918-d6a58a75abb4" IssueInstant="2022-10-22T10:30:12.549Z" Version="2.0">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://mock-idp</saml2: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/2001/04/xmldsig-more#rsa-sha256"/>
        <ds:Reference URI="#_b3a92133-c190-4972-8918-d6a58a75abb4">
          <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#">
              <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"></ec:InclusiveNamespaces>
            </ds:Transform>
          </ds:Transforms>
          <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <ds:DigestValue>uQjVT+t142IInUWHcPdNka2xP46+gUNx+W0lfzs2fB8=</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>dosUeZ+/7/sG4mbWGXmUW6yi2hlzx00REmVd1tvnIjm10dbzIvzfjJGW3yZ8FPW6Vj/ZCW/bmZY/vKSOO3T3S2XCPiKPERS5Z/4LILh2hEkWSIGehXTfmDxwsCnyDOK1Ejy7Exjt8TbMWiD9pDQKXiGykXnroa8I+KI9MHMKdP13SlxZuHD93lmwmapXax6cw4Zm8MB1v9CDgUfFRV4jagvTYNqrKVt7emBbnc2xxQtiaLd3q6NNQgUXNAS5W1BoQRJwL3CjJ72sPTYQxOHdqqcLQNjMnpRX7Rdq80e8ddz63kfVkl0UpRioYKQTFp8S6e2r1CoIOjM0pa3heNkRsw==</ds:SignatureValue>
    </ds:Signature>
    <saml2:Subject>
      <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">wewe</saml2:NameID>
      <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml2:SubjectConfirmationData InResponseTo="ahgg4a45deh9i67h0f2iedga0755g" NotOnOrAfter="2022-10-22T18:30:12.546Z" Recipient="http://192.168.0.104:9090/saml/SSO"/>
      </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions NotBefore="2022-10-22T10:27:12.546Z" NotOnOrAfter="2022-10-22T10:33:12.546Z">
      <saml2:AudienceRestriction>
        <saml2:Audience>http://mock-sp</saml2:Audience>
      </saml2:AudienceRestriction>
    </saml2:Conditions>
    <saml2:AuthnStatement AuthnInstant="2022-10-22T10:30:12.547Z">
      <saml2:AuthnContext>
        <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef>
        <saml2:AuthenticatingAuthority>http://mock-idp</saml2:AuthenticatingAuthority>
      </saml2:AuthnContext>
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:displayName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">wewe</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:cn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:sn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:eduPersonPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:dir:attribute-def:mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:terena.org:attribute-def:schacHomeOrganizationType" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">ererer</saml2:AttributeValue>
      </saml2:Attribute>
      <saml2:Attribute Name="urn:mace:terena.org:attribute-def:schacHomeOrganization" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
        <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">example.com</saml2:AttributeValue>
      </saml2:Attribute>
    </saml2:AttributeStatement>
  </saml2:Assertion>
</saml2p:Response>

Response多了一個InResponseTo屬性,這個值就是前面AuthnRequest的ID值,然后后面第一個子Signature標簽含義同AuthnRequest一樣,這里看下其他標簽。

Status

IDP認證用戶結果的標志,這里為success,表示用戶認證成功。

Assertion

Assertion是斷言的意思,這里面包含的是用戶的一些基本信息和屬性。

其中包含的Issuer標簽代表的意思和AuthnRequest一樣,Signature也是類似,不過簽名的內容不一樣,在后續代碼細節分析會看到簽的是哪一部分。

Subject

  • NameID: 標識符,其中的Format屬性為unspecified,表示IdP為其定義了格式,并假設SP知道如何解析來自 IdP的格式數據響應。例如,IdP給出一個格式數據"UserName=XXXXX Country=US",SP得到斷言,可以解析得到UserName為"XXXXX"。這里我們就只是一個字符username字符串格式,表示用戶名為wewe
  • SubjectConfirmation: 用戶如何進行認證的,這里method使用的bearer方式
  • SubjectConfirmationData: InResponseTo表示響應給誰,NotOnOrAfter表示在這之前有效,Recipient表示接收端點
  • Conditions: 限定Assertion有效時間,其中的帶Audience相關標簽是接收者的一些信息
  • AuthnStatement: idp對用戶認證使用方式,認證機構等信息
  • AttributeStatement: 和用戶有關的一些屬性

通過OpenSAML源碼看SAML SSO細節

還是之前那個項目,這里著重看SP生成AuthnRequest和IDP生成AuthnResponse生成以及IDP收到AuthnRequest和SP收到AuthnResponse的處理,其中的簽名和摘要以及涉及到的一些轉換和校驗部分是重點。

SP生成AuthnRequest

到摘要處調用棧如下:

calculateDigest:719, Reference (org.apache.xml.security.signature)
generateDigestValue:406, Reference (org.apache.xml.security.signature)
generateDigestValues:206, Manifest (org.apache.xml.security.signature)
sign:609, XMLSignature (org.apache.xml.security.signature)
signObject:77, Signer (org.opensaml.xml.signature)
signMessage:193, BaseSAML2MessageEncoder (org.opensaml.saml2.binding.encoding)
doEncode:109, HTTPPostEncoder (org.opensaml.saml2.binding.encoding)
encode:52, BaseMessageEncoder (org.opensaml.ws.message.encoder)
sendMessage:224, SAMLProcessorImpl (org.springframework.security.saml.processor)
sendMessage:42, ConfigurableSAMLProcessor (mujina.sp)
sendMessage:148, AbstractProfileBase (org.springframework.security.saml.websso)
sendAuthenticationRequest:107, WebSSOProfileImpl (org.springframework.security.saml.websso)
initializeSSO:225, SAMLEntryPoint (org.springframework.security.saml)
commence:152, SAMLEntryPoint (org.springframework.security.saml)
sendStartAuthentication:215, ExceptionTranslationFilter

調用棧就是整個生成AuthnRequest的流程,這里主要看下摘要,摘的是哪一部分:

<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://192.168.0.104:9090/saml/SSO" Destination="http://192.168.0.104:8080/SingleSignOnService" ForceAuthn="true" ID="a534936dfbc0a19e32g890f5f33i4ee" IsPassive="false" IssueInstant="2022-10-31T13:16:48.841Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">http://mock-sp</saml2:Issuer></saml2p:AuthnRequest>

xml內容是經過兩個transform處理之后的內容:

Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"轉換器會排除AuthnRequest中的Signature標簽的內容,Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"會將xml規范化(移除注釋等一些操作)并壓縮,最后得到的內容就如上了。

然后對這一部分內容進行SHA-256摘要算法:

后續進行簽名,到簽名處調用棧如下:

engineSign:190, RSASignature (sun.security.rsa)
engineSign:1235, Signature$Delegate (java.security)
sign:598, Signature (java.security)
engineSign:133, SignatureBaseRSA (org.apache.xml.security.algorithms.implementations)
sign:174, SignatureAlgorithm (org.apache.xml.security.algorithms)
sign:628, XMLSignature (org.apache.xml.security.signature)
signObject:77, Signer (org.opensaml.xml.signature)
signMessage:193, BaseSAML2MessageEncoder (org.opensaml.saml2.binding.encoding)
doEncode:109, HTTPPostEncoder (org.opensaml.saml2.binding.encoding)
encode:52, BaseMessageEncoder (org.opensaml.ws.message.encoder)
sendMessage:224, SAMLProcessorImpl (org.springframework.security.saml.processor)
sendMessage:42, ConfigurableSAMLProcessor (mujina.sp)
sendMessage:148, AbstractProfileBase (org.springframework.security.saml.websso)
sendAuthenticationRequest:107, WebSSOProfileImpl

使用SP的私鑰(在application.yml文件中有配置),對SingedInfo進行簽名:

<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod><ds:Reference URI="#a5856d7b1876hii3i40cda0c3fc38h"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod><ds:DigestValue>UEOuyyx4dWr3X0XoQryWQfSzNpXleQ5zSg9LayAEX7E=</ds:DigestValue></ds:Reference></ds:SignedInfo>

經過這些處理之后,看到的AuthnRequest的xml就是之前抓包解碼看到的了:

最后還有一個http post傳輸base64編碼處理,所以抓包看到的也是base64編碼。

IDP收到AuthnRequest的處理

mujina.idp.SAMLMessageHandler#extractSAMLMessageContext中對SP發送的AuthnRequest進行了提取并校驗:

對AuthnRequest校驗的安全策略只檢測IssueInstant是否過期,沒有其他策略。然后還有validatorSuites檢測,可以看到有兩種類型的validator,每個下面有多個標簽對應的具體validator。不過測試發現這里IDP沒有對AuthnRequest進行證書校驗、簽名校驗、摘要校驗的操作。

IDP生成AuthnResponse

對Assertion簽名,調用棧如下:

calculateDigest:719, Reference (org.apache.xml.security.signature)
generateDigestValue:406, Reference (org.apache.xml.security.signature)
generateDigestValues:206, Manifest (org.apache.xml.security.signature)
sign:609, XMLSignature (org.apache.xml.security.signature)
signObject:77, Signer (org.opensaml.xml.signature)
signAssertion:153, SAMLBuilder (mujina.saml)
sendAuthnResponse:123, SAMLMessageHandler (mujina.idp)
doSSO:77, SsoController (mujina.idp)
singleSignOnServicePost:55, SsoController (mujina.idp)

摘要內容如下:

摘要內容:

<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_2f36cf83-55f7-415e-ba10-5d8188c58e31" IssueInstant="2022-11-01T14:00:37.681Z" Version="2.0"><saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://mock-idp</saml2:Issuer><saml2:Subject><saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">111111</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData InResponseTo="a4ebjf264d9b7dja4hicahibc3d2jf8" NotOnOrAfter="2022-11-01T22:00:37.677Z" Recipient="http://192.168.0.104:9090/saml/SSO"></saml2:SubjectConfirmationData></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore="2022-11-01T13:57:37.678Z" NotOnOrAfter="2022-11-01T14:03:37.678Z"><saml2:AudienceRestriction><saml2:Audience>http://mock-sp</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2022-11-01T14:00:37.678Z"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef><saml2:AuthenticatingAuthority>http://mock-idp</saml2:AuthenticatingAuthority></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="urn:mace:dir:attribute-def:displayName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">111111</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:oasis:names:tc:SAML:attribute:subject-id" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">sdsdsdsd</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:cn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:sn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:eduPersonPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:terena.org:attribute-def:schacHomeOrganization" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">example.com</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion>

這里也是采用了和之前SP生成AuthnRequest相同的transform算法,所以排除了Signature標簽以及進行了規范化處理。后面還會對SingedInfo進行簽名,和AuthnRequest簽名方式一樣的方式,簽名的私鑰在application.yml文件中有配置。

后面還會對Response標簽進行一次摘要和簽名:

calculateDigest:719, Reference (org.apache.xml.security.signature)
generateDigestValue:406, Reference (org.apache.xml.security.signature)
generateDigestValues:206, Manifest (org.apache.xml.security.signature)
sign:609, XMLSignature (org.apache.xml.security.signature)
signObject:77, Signer (org.opensaml.xml.signature)
signMessage:193, BaseSAML2MessageEncoder (org.opensaml.saml2.binding.encoding)
signMessage:97, HTTPPostSimpleSignEncoder (org.opensaml.saml2.binding.encoding)
doEncode:109, HTTPPostEncoder (org.opensaml.saml2.binding.encoding)
encode:52, BaseMessageEncoder (org.opensaml.ws.message.encoder)
sendAuthnResponse:145, SAMLMessageHandler (mujina.idp)
doSSO:77, SsoController (mujina.idp)
singleSignOnServicePost:55, SsoController (mujina.idp)

摘要內容:

<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="http://192.168.0.104:9090/saml/SSO" ID="_cac5ad52-f303-4356-b061-177f2bc4247c" InResponseTo="a4ebjf264d9b7dja4hicahibc3d2jf8" IssueInstant="2022-11-01T14:00:37.675Z" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://mock-idp</saml2:Issuer><saml2p:Status><saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"></saml2p:StatusCode></saml2p:Status><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_2f36cf83-55f7-415e-ba10-5d8188c58e31" IssueInstant="2022-11-01T14:00:37.681Z" Version="2.0"><saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://mock-idp</saml2: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:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod><ds:Reference URI="#_2f36cf83-55f7-415e-ba10-5d8188c58e31"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"></ec:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod><ds:DigestValue>XUf3yZB7j4wKYhl3K7Cp4dhfe/E0qKs3a8at+WjZ4Sc=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>i97x4tGq3whwLpqCIXRsLAy2pn0Wx0+yuHBreiMTwGm4Ekao3DfFvzSfPN5rMVATV59ntBonmUayrZExxsEyVm2xMSFBBEx0JO2stJ6dx2XXPgIiHr7tV5oH9V9wK5OwG1rAHRDMyg4IBCQzLlQrrBZwMCAu/G9FaSw0vBq/COSS8YBrW5/vBH4tS9/NdtTQiXiDoXnGSVYZvXtE0W5anNAUiDytmQhai4dy4Yim/rtKRjIXJVAWD9djCcuR7N//7MWRw1XjWlr1RTwm2TtVvGEY5FL5fVRjdsXJdcc7HNq3UUMQnBpY5RKe+xhri8oZqBc6dmyF96PEUY54EVTdWw==</ds:SignatureValue></ds:Signature><saml2:Subject><saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">111111</saml2:NameID><saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml2:SubjectConfirmationData InResponseTo="a4ebjf264d9b7dja4hicahibc3d2jf8" NotOnOrAfter="2022-11-01T22:00:37.677Z" Recipient="http://192.168.0.104:9090/saml/SSO"></saml2:SubjectConfirmationData></saml2:SubjectConfirmation></saml2:Subject><saml2:Conditions NotBefore="2022-11-01T13:57:37.678Z" NotOnOrAfter="2022-11-01T14:03:37.678Z"><saml2:AudienceRestriction><saml2:Audience>http://mock-sp</saml2:Audience></saml2:AudienceRestriction></saml2:Conditions><saml2:AuthnStatement AuthnInstant="2022-11-01T14:00:37.678Z"><saml2:AuthnContext><saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml2:AuthnContextClassRef><saml2:AuthenticatingAuthority>http://mock-idp</saml2:AuthenticatingAuthority></saml2:AuthnContext></saml2:AuthnStatement><saml2:AttributeStatement><saml2:Attribute Name="urn:mace:dir:attribute-def:displayName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">111111</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:oasis:names:tc:SAML:attribute:subject-id" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">sdsdsdsd</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:cn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:sn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Doe</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:eduPersonPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">John</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:dir:attribute-def:mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">j.doe@example.com</saml2:AttributeValue></saml2:Attribute><saml2:Attribute Name="urn:mace:terena.org:attribute-def:schacHomeOrganization" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"><saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">example.com</saml2:AttributeValue></saml2:Attribute></saml2:AttributeStatement></saml2:Assertion></saml2p:Response>

注意此時摘要包含了Assertion以及Assertion所有子標簽,Response中的Signature標簽也因為應用了和之前相同的transform,所以不包含在摘要中。后面還會對SingedInfo進行簽名后,最終的xml就是抓包看到的樣子。

SP收到AuthnResponse的處理

evaluate:51, BasicSecurityPolicy (org.opensaml.ws.security.provider)
processSecurityPolicy:132, BaseMessageDecoder (org.opensaml.ws.message.decoder)
decode:83, BaseMessageDecoder (org.opensaml.ws.message.decoder)
decode:70, BaseSAML2MessageDecoder (org.opensaml.saml2.binding.decoding)
retrieveMessage:105, SAMLProcessorImpl (org.springframework.security.saml.processor)
retrieveMessage:172, SAMLProcessorImpl (org.springframework.security.saml.processor)
attemptAuthentication:85, SAMLProcessingFilter (org.springframework.security.saml)
doFilter:223, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)
doFilter:213, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)

主要的校驗點是兩個securityPolicies:

SAML2HTTPPostSimpleSignRule是校驗post傳輸中數據的簽名,這個很好理解。

SAMLProtocolMessageXMLSignatureSecurityPolicyRule是校驗Saml Response中的簽名,首先會從本地提取IDP的證書(在classpath:metadata/mujina.local.idp.metadata.xml中有配置),這里并沒有從傳過來的Response中提取證書,而是用配置好的信任的證書:

調用棧如下:

checkSignatureValue:723, XMLSignature (org.apache.xml.security.signature)
validate:69, SignatureValidator (org.opensaml.xml.signature)
verifySignature:142, BaseSignatureTrustEngine (org.opensaml.xml.signature.impl)
validate:100, BaseSignatureTrustEngine (org.opensaml.xml.signature.impl)
validate:100, ExplicitKeySignatureTrustEngine (org.opensaml.xml.signature.impl)
validate:49, ExplicitKeySignatureTrustEngine (org.opensaml.xml.signature.impl)
evaluate:104, BaseTrustEngineRule (org.opensaml.ws.security.provider)
evaluate:91, BaseTrustEngineRule (org.opensaml.ws.security.provider)
doEvaluate:128, SAMLProtocolMessageXMLSignatureSecurityPolicyRule (org.opensaml.common.binding.security)
evaluate:107, SAMLProtocolMessageXMLSignatureSecurityPolicyRule (org.opensaml.common.binding.security)
evaluate:51, BasicSecurityPolicy (org.opensaml.ws.security.provider)
processSecurityPolicy:132, BaseMessageDecoder (org.opensaml.ws.message.decoder)
decode:83, BaseMessageDecoder (org.opensaml.ws.message.decoder)
decode:70, BaseSAML2MessageDecoder (org.opensaml.saml2.binding.decoding)
retrieveMessage:105, SAMLProcessorImpl (org.springframework.security.saml.processor)
retrieveMessage:172, SAMLProcessorImpl (org.springframework.security.saml.processor)
attemptAuthentication:85, SAMLProcessingFilter (org.springframework.security.saml)
doFilter:223, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)
doFilter:213, AbstractAuthenticationProcessingFilter

從證書中提取public key,用public key對SignatureValue解密,解密值是Signedinfo的摘要,對Signedinfo重新摘要,和解密的摘要值進行對比。接著還會對比DigestValue摘要值,這個值是Response中除了Response子標簽Signature的摘要,這里的處理是重新計算這部分的摘要,然后和DigestValue進行對比:

當然過程中還存在其他校驗,例如status的校驗等。

后面還會對Assertion進行校驗:

processAuthenticationResponse:301, WebSSOProfileConsumerImpl (org.springframework.security.saml.websso)
authenticate:88, SAMLAuthenticationProvider (org.springframework.security.saml)
authenticate:182, ProviderManager (org.springframework.security.authentication)
attemptAuthentication:92, SAMLProcessingFilter (org.springframework.security.saml)
doFilter:223, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)
doFilter:213, AbstractAuthenticationProcessingFilter (org.springframework.security.web.authentication)

校驗方式和Response中的校驗一致,證書用的本地配置的而不是從Assertion中提取,校驗了Assertion中的Sianature、摘要信息,還校驗了Conditions是否過期,Subject中的接收者是否是預期的接收端點等校驗,這一系列校驗之后,就成功返回一個Credential,里面包含了用戶的一些信息。

SAML校驗過程中存在的安全隱患

對于簽名問題,在Bypassing SAML 2.0 SSO with XML Signature Attacks這篇文章中提到的幾個問題感覺很好的說明了SAML可能存在的安全隱患:

  • 簽名是否是必須的?可能一些SAML的實現從請求中判斷是否攜帶了Signature,攜帶了就校驗,沒攜帶就不校驗;或者設置一個簽名校驗開關讓開發者進行處理,而開發者可能并不熟悉沒有打開強制驗證等情況
  • 簽名是否經過驗證?雖然生成AuthnRequest和Response都進行了簽名,但是各自收到SAML消息時沒有進行簽名驗證的情況
  • 簽名是否來自正確的簽名者?X509Certificate包含簽名者信息,如果沒有校驗是否是信任的證書,那么可以偽造證書,然后對SAML消息進行篡改,重新簽名
  • 是否對響應中正確的部分進行簽名?SAML標準允許的簽名存在的位置僅有兩處:Response、Assertion,沒有人僅僅為了使用SAML,就完整地實現復雜的XML簽名機制。這一標準是通用的,標準的實現及其軟件庫也是如此。所以如果某些庫如果驗證簽名沒有驗證到正確的位置,就可以將簽名引用到文檔的不同位置,并且讓接受者認為簽名是有效的,造成XSW攻擊

Burp中有一個SAML Raider插件,可以很方便的進行修改和偽造SAML攻擊,不過有時候也需要手動構造,所以理解SAML的處理流程也是有必要的。

在《Hacking the Cloud With SAML》中提到一個新的攻擊面,就是SignedInfo的校驗和摘要校驗的先后順序問題,從上面SP收到AuthnResponse的處理一節可以看到,摘要校驗是會先經過transform處理的,而摘要的計算不包括Signature標簽內容,所以如果先進行了摘要校驗,那么transforms下的操作空間就不受限制,可以任意設置transform,這個ppt中也提到了兩個CVE(CVE-2022-34716、CVE-2022-34169),是transform進行攻擊很好的例子。

Demo項目中存在的問題

Demo中使用的OpenSAML是比較新,經過測試,SP收到AuthnResponse的處理是沒有上面的問題的,他的校驗順序如下:

  • 使用本地信任的證書
  • 校驗SignedInfo
  • 校驗摘要

所以Response的校驗沒有問題。

但是IDP收到AuthnRequest的處理只校驗了Instant是否過期,不過因為沒有處理簽名和摘要的流程,所以不存在其他攻擊的可能。不過IDP是從AuthnRequest拿的AssertionConsumerServiceURL,沒有校驗是否是預期的,所以后面將Reponse發送回去時,會導致一個SSRF問題,這一塊的處理應該是開發人員來做的,不是庫的問題。

最后

由于用的是比較新版的OpenSAML進行調試,在調試過程中可以發現一些修復痕跡,例如對XSW、ds:Object元素攻擊的修復等。之前看到SAML或者SAML的漏洞報告就頭大,因為里面涉及到了簽名和摘要,而且還是對XML簽名和摘要,是像字符串那樣摘要和簽名嗎,不是的話又是如何簽名XML,如何摘要XML,如何校驗XML,我要攻擊怎么篡改偽造,需要改哪些數據,怎么重新計算簽名和摘要等,現在調試了一遍算是很清晰了。

參考

https://research.aurainfosec.io/bypassing-saml20-SSO/

https://drive.google.com/file/d/1p1tTTIjg3RoJecYSU3CetvNw6-ZZdMXn/view

https://github.com/OpenConext/Mujina


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2006/