SAML2.0 協議初識(二)---Service Provider(SP)


上一節,我們初步認識了 SAML 協議的概念和工作流程,這一節將介紹 SP 端的一些細節。

通常情況下,SP 端是請求發起端,即當用戶訪問 SP 端的受保護資源時,由 SP 端向認證中心(IDP 端)發起認證請求。最終請求會回到 SP 端並由 SP 端將受保護資源授權給用戶。

假設,SP 有一受保護靜態資源 index.html,通常情況下,為了保護該靜態資源,SP 可以選擇用過濾器對訪問該資源的請求進行過濾,如果該用戶已被授權,則將 index.html 返回給用戶;否則將生成認證請求到 IDP。

首先,我們先看一個有 SP 端生成的認證請求參數,它是普通的 xml 文檔:

1 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2 <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="http://localhost:8080/sp/consumer" Destination="http://localhost:8080/idp/sso" 
ID
="3983b844-5f42-4c66-b476-f69704f00b5b" IssueInstant="2017-12-21T08:35:56.975Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> 3 <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://localhost:8080/sp</saml:Issuer> 4 <samlp:NameIDPolicy AllowCreate="true" Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"/> 5 </samlp:AuthnRequest>

該請求根節點是 <samlp:AuthnRequest> 來表明是一個認證請求,有如下幾個參數:

1、 AssertionConsumerServiceURL 斷言消費服務地址,即當 IDP 認證成功后響應返回的地址
2、 Destination 目標地址,即 IDP 接收請求的地址
3、 ID 該請求的唯一標識
4、 IssueInstant 請求的時間
5、 ProtocolBinding SP 聲明此次通信的綁定方式,不同的綁定方式意味着不同的通信流程,SAML2.0 主要包括:HTTP-Artifact,HTTP-POST,HTTP-Redirect,SOAP 等幾種綁定方式。
6、 Version 版本號
7、 saml:Issuer SP 的 Id 標識
8、 samlp:NameIDPolicy IDP 對於用戶身份的標識;NameID policy 是 SP 關於 NameID 是如何被創建的說明;Format 指明 SP 需要返回什么類型的標識(SAML Artifact);屬性AllowCreate指明 IDP 是否被允許當發現用戶不存在時創建用戶賬號。

創建 AuthnRequest 對象采用了開源的 opensaml,代碼如下:

 1 /**
 2  * 創建AutheRequest對象 * @param idpSsoUrl
 3   * @param acsUrl
 4   * @param spEntityId
 5   * @return
 6   */
 7 public AuthnRequest createRequest(String idpSsoUrl,String acsUrl,String spEntityId){
 8     AuthnRequest authnRequest = create(AuthnRequest.class,AuthnRequest.DEFAULT_ELEMENT_NAME);
 9   authnRequest.setIssueInstant(new DateTime());
10   authnRequest.setDestination(idpSsoUrl);
11   authnRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI);
12   authnRequest.setID(UUID.randomUUID().toString());
13   authnRequest.setAssertionConsumerServiceURL(acsUrl);
14 
15   Issuer issuer = create(Issuer.class,Issuer.DEFAULT_ELEMENT_NAME);
16   issuer.setValue(spEntityId);
17   authnRequest.setIssuer(issuer);
18 
19   NameIDPolicy nameIDPolicy = create(NameIDPolicy.class,NameIDPolicy.DEFAULT_ELEMENT_NAME);
20   nameIDPolicy.setAllowCreate(true);
21   nameIDPolicy.setFormat(NameID.UNSPECIFIED);
22   authnRequest.setNameIDPolicy(nameIDPolicy);
23  return authnRequest;
24 }

生成對象后轉化成字符串:

1 Document document = asDOMDocument(authnRequest);
2 DOMSource source=new DOMSource(document);
3 TransformerFactory tf = TransformerFactory.newInstance();
4 Transformer former=tf.newTransformer();
5 former.setOutputProperty(OutputKeys.STANDALONE, "yes");
6 StringWriter sw = new StringWriter();
7 StreamResult sr = new StreamResult(sw);
8 former.transform(source, sr);
9 String result=sw.toString();

將 xml 字符串進行 base64 編碼后拼接成認證請求地址發起認證請求,認證請求地址示例如下:

http://localhost:8080/idp/sso?SAMLRequest=fZJdT8IwFIb/SnPuy7qhwBqGQYmRxA8i0wvvSneQJl07ezo//r1zQKKJets+ed+e53R69l5b9oqBjHcFpAMBDJ32lXHPBTyUl3wCjKJylbLeYQHOw9lsSqq2jZy3cefu8aVFiqzLcST7iwLa4KRXZEg6VSPJqOV6fnMts4GQTfDRa2+BzYkwxK74wjtqawxrDK9G48P9dQG7GBuZJNZrZXeeopyIiUioSfQBBrboeo1TsX/677ypmoTIA1suCsiHW9SjVPBTvVX8JB/lPNfVho+z0ViMhgKHm9OOJGpx6b6GjgVkIh3zNONZWopcZpnMJgMhTp6ArQ5znBu3t/Xf0Js9RPKqLFd8dbcugT0erXcA7J3Kvjx8k/l/rDoahNlfvqbJt+Dj5m67pOVi5a3RH2xurX+7CKhit98YWgR26UOt4t/d6SDtT0zFtz0qW0cNarM1WEEy25f+/CGzTw==

后續就是 IDP 收到該請求后解析、認證、返回的過程了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM