首页 > 解决方案 > 如何使用 Angular 调用基于 SAML(http-post 绑定)的 REST API?

问题描述

我有受 SAML 2.0(POST 绑定)保护的 OData REST API,并且我有 Angular 2+ 客户端应用程序。如何使用 Angular 应用程序调用这些 REST API?

当我使用 Angular HTTP 客户端时 import {Http, RequestOptions, Request, RequestMethod} from '@angular/http';

我收到带有继续按钮的表单注意:由于您的浏览器不支持 JavaScript,您必须按一次继续按钮才能继续。

如果我直接在浏览器中点击相同的 REST API URL,则浏览器会重定向到 IDP,然后在成功验证后,IdP 会将其重定向回 REST API。

在 Postman 上观察到相同的行为,但他们正在通过启用 JS 脚本预览来修复它。

这是我尝试过的 Angular 代码:

this.POST('https://<RESTAppfqdn>/odata', {"ID": "2"}).subscribe(data => {
console.log(data)
})
}

POST(url, data) {
const headers = Object.assign({
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json;vnd.ptc.ilm.webui2.0=true;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
});
var requestoptions = new RequestOptions({
method: RequestMethod.Post,
url: url,
headers: headers,
body: data
})

return this.http.request(new Request(requestoptions))
.pipe(map(res => res.json()));
}

这是我可以在浏览器的网络选项卡中看到的响应:

<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="https&#x3a;&#x2f;&#x2f;<Idpfqn>&#x3a;9031&#x2f;idp&#x2f;SSO.saml2" method="post">
            <div>

                <input type="hidden" name="SAMLRequest" value="PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDJwOkF1dGhuUmVxdWVzdCB4bWxuczpzYW1sMnA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgQXNzZXJ0aW9uQ29uc3VtZXJTZXJ2aWNlVVJMPSJodHRwczovL0tJU0pBREhBVjJMMS9zYW1sL1NTTyIgRGVzdGluYXRpb249Imh0dHBzOi8va2lzamFkaGF2MmwxLnB0Y25ldC5wdGMuY29tOjkwMzEvaWRwL1NTTy5zYW1sMiIgRm9yY2VBdXRobj0iZmFsc2UiIElEPSJhM2UzOTMyZjAzNTNmNWI3NTFoYmc4ZWpmY2lkNTViIiBJc1Bhc3NpdmU9ImZhbHNlIiBJc3N1ZUluc3RhbnQ9IjIwMTktMDQtMjVUMDY6MTc6MjUuOTQzWiIgUHJvdG9jb2xCaW5kaW5nPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YmluZGluZ3M6SFRUUC1QT1NUIiBWZXJzaW9uPSIyLjAiPjxzYW1sMjpJc3N1ZXIgeG1sbnM6c2FtbDI9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vS0lTSkFESEFWMkwxL3NhbWwvbWV0YWRhdGE8L3NhbWwyOklzc3Vlcj48ZHM6U2lnbmF0dXJlIHhtbG5zOmRzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHM6U2lnbmVkSW5mbz48ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz48ZHM6UmVmZXJlbmNlIFVSST0iI2EzZTM5MzJmMDM1M2Y1Yjc1MWhiZzhlamZjaWQ1NWIiPjxkczpUcmFuc2Zvcm1zPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L2RzOlRyYW5zZm9ybXM+PGRzOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyNzaGExIi8+PGRzOkRpZ2VzdFZhbHVlPlNDc3dxRG5FTThNWEJvSnZkRGhrdEE3dGF5VT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+YkxTd3pjRFhYUmNQV1VYa2hHbXB4RXZEQ3JlRWFpc2tka2drTzl5eGpkdGFlalhnSEVBNHRQNWhuL2FyRVh4T0NxWHlmWnFBRXFZZFduTE5vODJyNXZoQ1F2SGhWdEJHTUY0T1FSbXlDT2FwUHRPamdINWtpRW1uaVVHNHduaEpERCsxRWR3L2x2ZFlJd0svSEhCSE8zV2p4eTZ3aW9hbUhMRGczYWNNM0QzdHNMMFR0VlM0RVZETncxeFBmeTdUWTd6WVZqYWUrcmZqRm9IZUlEQlZYdFNnS2xSL2RHbW1DMXBaTDFydWVsZHkzSEJRV3dYVWx5S1NRa09oNU9VWnBCeWttMHBERDhmNnA4UVV3Uy8zTEtxd3hvc1NiWlVIMlJoUHI0RFIwTDMwQjNzSmlka1JKMGI0eUdHNlFzZnlGY3lVZERxdHVDS3FhVkpMR1htSXNnPT08L2RzOlNpZ25hdHVyZVZhbHVlPjxkczpLZXlJbmZvPjxkczpYNTA5RGF0YT48ZHM6WDUwOUNlcnRpZmljYXRlPk1JSURYVENDQWtXZ0F3SUJBZ0lFVXZvcnFEQU5CZ2txaGtpRzl3MEJBUXNGQURCZk1Rc3dDUVlEVlFRR0V3SnBiakVMTUFrR0ExVUUNCkNCTUNiV2d4RFRBTEJnTlZCQWNUQkhCMWJtVXhEREFLQmdOVkJBb1RBM0IwWXpFUE1BMEdBMVVFQ3hNR2NIUmpibVYwTVJVd0V3WUQNClZRUURFd3hMU1ZOS1FVUklRVll5VERFd0hoY05NVGt3TkRJME1UZzBOekV3V2hjTk1qQXdOREU0TVRnME56RXdXakJmTVFzd0NRWUQNClZRUUdFd0pwYmpFTE1Ba0dBMVVFQ0JNQ2JXZ3hEVEFMQmdOVkJBY1RCSEIxYm1VeEREQUtCZ05WQkFvVEEzQjBZekVQTUEwR0ExVUUNCkN4TUdjSFJqYm1WME1SVXdFd1lEVlFRREV3eExTVk5LUVVSSVFWWXlUREV3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXcNCmdnRUtBb0lCQVFDblM2MmdHQ2llcHZJMXFVdCt4a1d1bjJRenlUWUlLay9DQ0w3WkxVUlkyVmluS0w4UUFGb0xnM0s2bGJCaTVPeEENCjI2em9ZY3cyVHJ5a1FmL2ZuSG04eXpEVWJWSzlmZ0NXVXBzT2tOZnUyMHVZUzc2cTBna0tmbGFFR2Q4UzFFUStVUGMvT0pkem5NTXMNCkpzckZldXZYMVpqZFMzWG9mZlBDZXcvOGdIQzR2dTU1V0tGSDhvODUxQWdRdXRrNzlUYUpYUm5zN0VpUVhvMkVBVnNTUWIrZXpoWGYNCnJuYXNMN1BhUGFWT0JQV1RBTi83VERSZEs4R1RiUHRrWG8wMnIxZnNoZk5rRW05VDhROTBFNmtmU1l6emt3MXByRktwY1RncTZsbmUNClFFMk4zNEpCVTdjUHlYVW8yRHVNNkxVVXZndWFLK2xDK05TamZENWliMFNTcDdtdkFnTUJBQUdqSVRBZk1CMEdBMVVkRGdRV0JCU28NCmxUS3d3dkoxdzBsZjkwZURPWTluUlY4bjJqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFYRzA4ZWphdjQxYWJtQS9jZkNZUFQrWVINClhQSnZzQ1F1YTJRempRSy9IMDdNclJsOTVCSkkzeUJEQ1pJaW9ndU5YbS9sbHVxYzV1VWJtekdBenBFM3MybnZtbjQ0bjBhUVYyd28NCkxja2NiWUZJUkNFRFhOZXFZUEUrZFVGdVgwSEJ5dlFqNU9FSU9wZTlYTzUrZ1lFUUlXZWxTZXFibUF0UmRuWi84ZWlFY3h6bEFaTlINCkRITDlxdjloK2doNFpPM3BkRVNLdWM3Z0NKODFXVGNueUN1QS9ZS1ZMR2lnM0plbEJJYkhwZTVXcXBaR3dPUG9WYk82cVViTzlHQjUNCmxVQkxYRlF3cmVSazlTV3JVQkV5Wi8yQ3ovY1UvVjRnSms4cGdTWTFPVHNOUmpGanZKVjd1TnBQeEsxam1nRkRsakV5aXpHay96WGENClJDNjE1VVhIbExpb093PT08L2RzOlg1MDlDZXJ0aWZpY2F0ZT48L2RzOlg1MDlEYXRhPjwvZHM6S2V5SW5mbz48L2RzOlNpZ25hdHVyZT48L3NhbWwycDpBdXRoblJlcXVlc3Q+"/>                

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

As Angular http client reside  in browser, browser should take care of handling this post form submission and redirection work but that is not happening. Is there any way by which i can tell browser to handle such responses?

标签: javaangularsingle-sign-onsaml-2.0spring-saml

解决方案


由于有从服务器收到的响应表单,我已经提交了该表单。因此,我在 index.html 中创建了一个 div(例如 auth),当响应包含表单时,然后提交它。这是那个代码。

if (res['error']['text']) {
 let authDiv = document.getElementById('auth') 
 authDiv.innerHTML = res['error']['text'] 
 var f1 = authDiv.children[1] 
 f1.submit() 
 return new HttpResponseFailAction([res['error']['text']]) 
}

但随后我们将面临另一个问题:

前任。必须显示从 IdP 收到的身份验证质询。

基本上,我们需要像浏览器一样行事,以及我们需要处理的任何即将到来的请求。

因此,我决定放弃这种方法,并将 SAML SSO 支持添加到客户端应用程序本身。


推荐阅读