【问题标题】:How to read value of SAML attribute received from the IdP?如何读取从 IdP 收到的 SAML 属性值?
【发布时间】:2016-02-14 03:41:25
【问题描述】:

我正在使用 Spring Security SAML 1.0.1,我想知道名为“eduPersonAffiliation”的 SAML 属性的值。我编写了一个实现org.springframework.security.saml.userdetails.SAMLUserDetailsService 接口和loadUserBySAML 方法的类,我正在这样做:

@Override
public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
    String eduPersonAffiliationAttributeName = "";
    // We need to use the "name" of the attribute to retrieve the value (not the friendly name)
    for (Attribute attribute : credential.getAttributes()) {
        if ("eduPersonAffiliation".equals(attribute.getFriendlyName())) {
            eduPersonAffiliationAttributeName = attribute.getName();
        }
    }
    Person user = usersService.getUser(
             credential.getAttribute(eduPersonAffiliationAttributeName).WHAT_TO_CALL_HERE?);
    return loadUserByUser(user);
}

getUser 方法需要一个字符串,该字符串应该是已连接用户的登录名。这个问题听起来很愚蠢,但我怎样才能访问给定属性名称的属性值?我看到一个返回List<XMLObject>org.opensaml.saml2.core.getAttributeValues 方法。怎么用?

谢谢!

【问题讨论】:

    标签: java spring-security spring-saml


    【解决方案1】:

    XmlObject 需要一些解包才能使用:

    private String getAttributeValue(XMLObject attributeValue)
    {
        return attributeValue == null ?
                null :
                attributeValue instanceof XSString ?
                        getStringAttributeValue((XSString) attributeValue) :
                        attributeValue instanceof XSAnyImpl ?
                                getAnyAttributeValue((XSAnyImpl) attributeValue) :
                                attributeValue.toString();
    }
    
    private String getStringAttributeValue(XSString attributeValue)
    {
        return attributeValue.getValue();
    }
    
    private String getAnyAttributeValue(XSAnyImpl attributeValue)
    {
        return attributeValue.getTextContent();
    }
    

    你可以遍历List<XmlObject>直到找到你需要的属性,然后调用上面的getAttributeValue(XmlObject)方法。

    根据这些XmlObjects 的实际情况(AttributeAttributeValue 等),您可能需要该算法的某些部分来完全解压它们:

    private final static String USERNAME_ATTRIBUTE_NAME = "urn:oid:0.9.2342.19200300.100.1.3"
    
    private String getUsername(Assertion assertion)
    {
        for (AttributeStatement attributeStatement : assertion.getAttributeStatements())
        {
            for (Attribute attribute : attributeStatement.getAttributes())
            {
                if (USERNAME_ATTRIBUTE_NAME.equals(attribute.getName()))
                {
                    List<XMLObject> attributeValues = attribute.getAttributeValues();
                    if (!attributeValues.isEmpty())
                    {
                        return getAttributeValue(attributeValues.get(0));
                    }
                }
            }
        }
        throw new IllegalArgumentException("no username attribute found");
    }
    

    在这种情况下,我使用标准 OID 作为电子邮件地址。实际上,这必须是可配置的,因为各种 IdP 使用不同的命名策略。这适用于 Shibboleth IdP 3。

    @StefanRasmusson 的 A Guide to OpenSAML 让我摆脱了获取 SAML 概念和能够实现自己的 SP 之间的障碍。

    Scott Cantor 在 shibboleth-users 邮件列表中也对我非常有帮助,从配置差距到高级安全架构问题等主题。 OpenSAML 社区(包括 Shibboleth)非常乐于助人,也很有主见,我喜欢这样。

    【讨论】:

    • @GrégoireColbert 为您完成这项工作或让您更接近答案。我可以和你一起迭代。
    • 谢谢阿兰,我明天试试!
    • 好东西。 @提及我,我会加入。
    • @GrégoireColbert 我现在已经修好了。感谢您指出这一点。
    • 这实际上是一段写得非常好的代码@Alain,像魅力一样工作:)
    【解决方案2】:

    访问属性值的另一种解决方案是通过 SAMLCredential.getAttributeAsString(String name)

    credential.getAttributeAsString(attribute.getName())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-09
      • 2016-10-31
      相关资源
      最近更新 更多