如何读取从IdP收到的SAML属性的值?

Gré*_*e C 5 java spring-security spring-saml

我正在使用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);
}
Run Code Online (Sandbox Code Playgroud)

getUser方法需要一个String,该String应该是已连接用户的登录名.问题听起来很愚蠢,但如何在给定属性名称的情况下访问属性值?我看到一个org.opensaml.saml2.core.getAttributeValues返回a 的方法List<XMLObject>.如何使用它?

谢谢!

Ala*_*Dea 17

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();
}
Run Code Online (Sandbox Code Playgroud)

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

根据它们XmlObject的真实含义(Attribute,AttributeValue等),您可能需要此算法的某些部分来完全解压缩它们:

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");
}
Run Code Online (Sandbox Code Playgroud)

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

@ StefanRasmusson的OpenSAML 指南让我超越了获取SAML概念和实现自己的SP之间的困境.

Scott Cantor在shibboleth-users邮件列表中对我的帮助非常大,从配置差距到高级安全架构问题等主题.OpenSAML社区(包括Shibboleth)非常有帮助和自以为是,我喜欢这样.