2016-07-05 199 views
4

我們有一個產品擁有一個客戶,我們在爲客戶實施SAML流程時使用Spring Security SAML作爲服務提供商,而idp位於客戶方。Spring SAML - 支持自定義SAML聲明

現在我們有另一位客戶也希望驗證與SAML一致,並且我們希望同一個SP爲此客戶實施SAML流程,另外第二個客戶將擁有2個SAML一個用於移動設備的流程,另一個用於其他設備使用相同的IDP。這兩個客戶的國內流離失所者是不同的。

問題

有兩個客戶例如斷言屬性是不同的,成功驗證行動不同的是,目前我們爲我們自己的實現之間存在一些差異。

也可能有更多的變化就像不同的綁定等...

我的問題是什麼是最好的選擇/最佳實踐來支持這樣的場景,並能夠延長我的SP支持更多的SAML與流Assertion屬性和更多配置的區別?

當我們使用Spring SAML時,我們是否應該爲每種SAML風格使用不同的Spring Security上下文文件?

並行使用多個上下文時是否存在線程安全問題?

回答

2

我的問題是什麼是最好的選擇/最佳實踐來支持這樣 場景,並能夠延長我的SP支持更多的SAML和斷言屬性和更多的配置差異流動 ?

要分支某些配置,例如Assertion屬性,您需要創建單獨的服務提供者。其他配置和服務可以共享。其他配置應該共享。例如,我使用單個自定義SAMLUserDetailsS​​ervice實現,將唯一EntityID從憑證中提取出來,並使用它爲每個IDP以不同的方式映射SAML屬性。

當我們使用Spring SAML時,我們是否應該爲每種SAML風格使用不同的Spring Security 上下文文件? 在並行使用 多個上下文時是否存在線程安全問題?

我不建議單獨運行多個安全上下文。根據我的經驗,在Spring SAML中涉及到很多配置,而且很可能你必須通過這種方式不必要地重複大量代碼。

在Spring SAML中,存在爲不同服務提供者使用不同別名的概念。我爲許多IDP設置了許多服務提供者,並且能夠使用一個Spring Security上下文並在需要處理差異的地方實現自定義服務。我沒有你的要求的完整列表,可能有一些不能在單一的春季安全環境中完成,但我會等待確保在採用該路線之前就是這種情況。

每個IDP之間會有什麼特別的區別?

我被限制在允許發佈的代碼中,但我已經包含了我可以提供的內容。

  • 入口點URL - 如果你有多個國內流離失所者在配置中設置一個別名,默認入口點URL將被

    "/saml/login/alias/" +productAlias+ "?idp=" + entityId;

    如果你是在負載平衡器,您可以將其配置爲將您想要的任何URL重寫爲客戶的URL。

  • 綁定和斷言 - 這些配置在每個服務提供商metadata.xml文件中,並且可能因每個客戶而不同。真正的挑戰是如何從已認證的SAML請求中提取屬性,並以可用的形式獲取它。

    我不知道是否有更好的方法來做到這一點,但我的要求是任何綁定可映射和可配置爲我配置的任何IDP。爲了做到這一點,我實施了一個自定義SAMLUserDetailsService。從SAMLCredential傳遞到該服務,您可以使用credential.getRemoteEntityID()拉起客戶的映射。從那裏你需要解析出憑證中的屬性。

解析SAML的例子屬性微軟和其他國內流離失所者

上成功/失敗
public class AttributeMapperImpl implements AttributeMapper { 

    @Override 
    public Map<String, List<String>> parseSamlStatements(List<AttributeStatement> attributeList) { 
     Map<String, List<String>> map = new HashMap<>(); 
     attributeList.stream().map((statement) -> parseSamlAttributes(statement.getAttributes())).forEach((list) -> { 
      map.putAll(list); 
     }); 
     return map; 
    } 

    @Override 
    public Map<String, List<String>> parseSamlAttributes(List<Attribute> attributes) { 
     Map<String, List<String>> map = new HashMap<>(); 
     attributes.stream().forEach((attribute) -> { 
      List<String> sList = parseXMLObject(attribute.getAttributeValues()); 
      map.put(attribute.getName(), sList); 
     }); 
     return map; 
    } 

    @Override 
    public List<String> parseXMLObject(List<XMLObject> objs) { 
     List<String> list = new ArrayList<>(); 

     objs.stream().forEach((obj) -> { 
      if(obj instanceof org.opensaml.xml.schema.impl.XSStringImpl){ 
       XSStringImpl xs = (XSStringImpl) obj; 
       list.add(xs.getValue()); 
      }else if(obj instanceof org.opensaml.xml.schema.impl.XSAnyImpl){ 
       XSAnyImpl xs = (XSAnyImpl) obj; 
       list.add(xs.getTextContent()); 
      } 
     }); 

     return list; 
    } 

    @Override 
    public String parseSamlStatementsToString(Map<String, List<String>> map) { 
     String values = ""; 
     Iterator it = map.entrySet().iterator(); 
     while (it.hasNext()) { 
      Map.Entry pair = (Map.Entry) it.next(); 
      values += pair.getKey() + "=" + pair.getValue() + " "; 
      it.remove(); // avoids a ConcurrentModificationException 
     } 
     return values; 
    } 

} 
  • 行動 - 有這樣做的許多可能的方式。我選擇在可訪問會話的控制器中使用單個終端,以便所有請求都取得成功。驗證成功後,我可以退出會話,查看用戶來自哪個IDP並相應地重定向他們。失敗有點難度,因爲完全有可能並且可能有些失敗會非常嚴重,以至於您不知道請求來自哪個IDP(即,如果saml消息使用錯誤的證書籤名)。
+0

idps之間的差異是入口點URL,綁定,成功和失敗的行爲和斷言......你能分享一個證明它的samle代碼嗎? –

+0

我在回答中添加了一些信息 – blur0224