【问题标题】:Spring LDAP returns same and incorrect objectSidSpring LDAP 返回相同且不正确的 objectSid
【发布时间】:2018-05-28 11:35:00
【问题描述】:

在我的 Spring Web 应用程序中,我无法从当前使用 Active Directory 帐户登录的用户检索正确的 objectId。所有属性似乎都有正确的值,但objectId 的值始终设置为S-1-5-21-1723711471-3183472479-4012130053-3220159935,我不知道它来自哪里。

WebSecurityConfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }

    private ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider =
                new ActiveDirectoryLdapAuthenticationProvider(LdapConfig.AD_DOMAIN, LdapConfig.AD_SERVER);
        provider.setUserDetailsContextMapper(new LdapUserDetailsContextMapper());
        return provider;
    }
}

LdapUserDetailsContextMapper

@Slf4j
public class LdapUserDetailsContextMapper implements UserDetailsContextMapper {
    @Override
    public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> collection) {
        log.info("username: " + username); //username is correct
        log.info("DN from ctx: " + ctx.getDn()); // returns correct DN
        byte[] byteSid = ctx.getStringAttribute("objectSid").getBytes();
        String sid = LdapUtils.convertBinarySidToString(byteSid);
        log.info("SID: " + sid); // S-1-5-21-1723711471-3183472479-4012130053-3220159935 everytime

        return new User(username, "notUsed", true, true, true, true,
                AuthorityUtils.createAuthorityList("ROLE_USER"));
    }

    @Override
    public void mapUserToContext(UserDetails userDetails, DirContextAdapter dirContextAdapter) {

    }
}

如何从 Active Directory 中获取正确的 SID?

【问题讨论】:

  • 所有用户都一样吗?
  • 是的,完全正确,它与我添加的任何用户都不匹配(我没有通过这个 SID 搜索整个目录)。
  • 不同用户的最后一块字符应该不同。如果不是,比较两个用户的sid的字节流,看是否匹配。 Sid 将是独一无二的。
  • ctx.getDn() 是您希望从中获取 SID 的用户帐户的 DN?
  • @GabrielLuci 是的 :)

标签: java spring spring-security active-directory spring-ldap


【解决方案1】:

我想答案就在这里:http://forum.spring.io/forum/spring-projects/data/ldap/66894-objectsid-and-ldaptemplate

在倒数第二篇文章中,他描述了您遇到的同样问题。在上一篇文章中,他描述了一个修复方法,就是将这个添加到 Bean 配置文件中:

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
    <property name="url" value="ldap://ldapserver.domain.com:389" />
    <property name="base" value="dc=domain,dc=com" />
    <property name="userDn" value="cn=binduser,cn=Users,dc=domain,dc=com" />
    <property name="password" value="bindpwd"/>
    <property name="baseEnvironmentProperties">
        <map>
        <entry key="java.naming.ldap.attributes.binary">
            <value>objectSid</value>
        </entry>
        </map>
    </property>
</bean>

您必须修改域的值,但我认为重要的部分是 baseEnvironmentProperties

This thread 还描述了一种编程方式来设置它(虽然,对于objectGuid,但你可以只交换属性)。

AbstractContextSource contextSource = (AbstractContextSource) ldapTemplate.getContextSource();
Map<String,String> baseEnvironmentProperties = new HashMap<String, String>();
baseEnvironmentProperties.put("java.naming.ldap.attributes.binary", "objectSid");
contextSource.setBaseEnvironmentProperties(baseEnvironmentProperties);
contextSource.afterPropertiesSet();

【讨论】:

  • 你能帮我把它添加到我的ActiveDirectoryLdapAuthenticationProvider吗?
  • 如果你更新你的 bean 配置文件,你应该不需要。如果这不是一个选项,那么我不确定。我知道 AD,但我不是 Java 开发人员,所以我自己对此有点迷茫。该代码块并没有真正说明ldapTemplate 变量的来源。我想这是缺少的部分。
【解决方案2】:

我通过在 configure 方法中添加环境属性来实现这一点:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers("/", "/home").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}

private ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider provider =
            new ActiveDirectoryLdapAuthenticationProvider(LdapConfig.AD_DOMAIN, LdapConfig.AD_SERVER);

// ************** NEW ENVIRONMENT PROPERTIES **********************************
    Map<String, Object> environmentProperties = new HashMap<>();
    environmentProperties.put("java.naming.ldap.attributes.binary", "objectsid");
    provider.setContextEnvironmentProperties(environmentProperties);
// ************** END OF NEW ENVIRONMENT PROPERTIES ***************************

    provider.setUserDetailsContextMapper(new LdapUserDetailsContextMapper());
    return provider;
    }
}

然后在 UserDetailContextMapper 中像这样读取它:

public class CustomUserDetailsContextMapper implements UserDetailsContextMapper {

private final static Logger logger = LoggerFactory.getLogger(CustomUserDetailsContextMapper.class);

@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
    logger.info(ctx.getDn().toString());
    byte[] byteSid = null;
    try {
        byteSid = (byte[]) ctx.getAttributes().get("objectsid").get();
    } catch (NamingException e) {
        e.printStackTrace();
    }
    String sid = LdapUtils.convertBinarySidToString(byteSid);
    logger.info("SID: {}", sid);

    return new User(username, "notUsed", true, true, true, true,
            AuthorityUtils.createAuthorityList("ROLE_USER"));    
}

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多