【问题标题】:How to override the NameID value in SAMLAuthenticationProvider?如何覆盖 SAMLAuthenticationProvider 中的 NameID 值?
【发布时间】:2016-02-20 14:09:59
【问题描述】:

我正在使用 Spring Security SAML 1.0.1。我的应用程序使用这个 XML 来配置 SAMLAuthenticationProvider bean:

<!-- SAML Authentication Provider responsible for validating of received SAML messages -->
<b:bean id="samlAuthenticationProvider" class="org.springframework.security.saml.SAMLAuthenticationProvider">
    <!-- OPTIONAL property: can be used to store/load user data after login -->
    <b:property name="userDetails">
        <b:bean class="eu.ueb.acem.services.auth.SamlAuthenticationUserDetailsService"/>
    </b:property>
    <b:property name="forcePrincipalAsString" value="false"/>
</b:bean>

“SamlAuthenticationUserDetailsS​​ervice”类实现了loadUserBySAML(SAMLCredential) 方法。如果用户在数据库中不存在,则创建它。

@Override
public Object loadUserBySAML(SAMLCredential credential) throws UsernameNotFoundException {
    logger.info("entering loadUserBySAML({})", credential);
    String userID = credential.getNameID().getValue();
    logger.info("{} is logged in", userID);
    Map<String, String> mapOfAttributesFriendlyNamesAndValues = new HashMap<String, String>();
    mapOfAttributesFriendlyNamesAndValues.put("eduPersonAffiliation", null);
    mapOfAttributesFriendlyNamesAndValues.put("eduPersonPrincipalName", null);
    mapOfAttributesFriendlyNamesAndValues.put("eduPersonPrimaryAffiliation", null);
    mapOfAttributesFriendlyNamesAndValues.put("supannEtablissement", null);
    mapOfAttributesFriendlyNamesAndValues.put("supannEntiteAffectationPrincipale", null);
    mapOfAttributesFriendlyNamesAndValues.put("supannOrganisme", null);
    mapOfAttributesFriendlyNamesAndValues.put("displayName", null);
    mapOfAttributesFriendlyNamesAndValues.put("mail", null);
    mapOfAttributesFriendlyNamesAndValues.put("givenName", null);
    mapOfAttributesFriendlyNamesAndValues.put("sn", null);
    mapOfAttributesFriendlyNamesAndValues.put("uid", null);

    for (Attribute attribute : credential.getAttributes()) {
        logger.info("attribute friendly name={}", attribute.getFriendlyName());
        if (mapOfAttributesFriendlyNamesAndValues.containsKey(attribute.getFriendlyName())) {
            // We set the values of the property
            for (XMLObject attributeValueXMLObject : credential.getAttribute(attribute.getName()).getAttributeValues()) {
                logger.info("We care about this attribute, getAttributeValue={}", getAttributeValue(attributeValueXMLObject));
                mapOfAttributesFriendlyNamesAndValues.put(attribute.getFriendlyName(), getAttributeValue(attributeValueXMLObject));
            }
        }
        else {
            logger.info("We don't care about this attribute");
        }
    }
    Person user = usersService.getUser(mapOfAttributesFriendlyNamesAndValues.get("eduPersonPrincipalName"));
    user.setLogin(mapOfAttributesFriendlyNamesAndValues.get("eduPersonPrincipalName"));
    user.setEmail(mapOfAttributesFriendlyNamesAndValues.get("mail"));
    user.setName(mapOfAttributesFriendlyNamesAndValues.get("displayName"));
    user.setAdministrator(true);
    user = usersService.updatePerson(user);
    logger.info("leaving loadUserBySAML");
    return loadUserByUser(user);
}

private UserDetails loadUserByUser(Person targetUser) {
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    // Roles
    if (targetUser.isAdministrator()) {
        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
    }
    else {
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
    }

    return new User(targetUser.getLogin(), targetUser.getPassword(),
            true, // enabled
            true, // account not expired
            true, // credentials not expired
            true, // account not locked
            authorities);
}

我有以下行为:

  • 我在我的 SP 上请求一个需要身份验证的页面
  • 我被重定向到 IDP(最好是发现服务)
  • IDP 正确返回凭据
  • 我的loadUserBySAML方法被调用
  • 如果用户不存在,则会在数据库中创建该用户,并使用与其电子邮件地址相同的登录名
  • 请求的页面加载并且创建的用户不会被重用,而是创建一个新用户,其登录名等于credential.getNameID().getValue() 的值(例如“_246558c0d7c514447292d750df577b6b”)。

问题:如何将凭证的“NameID”属性设置为电子邮件地址?

我已多次阅读the documentation 的“9.4 身份验证对象”部分,但我仍然不明白如何告诉 Spring Security 我的 UserDetails 对象应该使用电子邮件地址而不是 NameID 值来引用.

【问题讨论】:

    标签: spring spring-security saml-2.0 spring-saml


    【解决方案1】:

    我认为问题可能在于默认情况下SAMLAuthenticationProvider 始终使用NameID,即使UserDetailsSAMLUserDetailsService 返回。这样做是为了向后兼容以前的版本,尽管我正在考虑更改它以避免混淆。

    为了使用从 UserDetails 返回的值,请将 bean SAMLAuthenticationProvider 上的属性 forcePrincipalAsString 设置为 false。

    【讨论】:

    • 我认为我已经设置了属性,如发布的配置所示。
    • 今天早上问题解决了!这是由 Renater 身份联合中的 SP 元数据的刷新延迟引起的。我很高兴!
    猜你喜欢
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 2014-02-15
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多