java - 具有 LDAP 身份验证的自定义权限

标签 java spring spring-security spring-boot

我发现很少有 Spring XML 配置示例使用 LDAP 登录并在自定义方法的帮助下配置登录用户的权限,而不是通过 LDAP。 不幸的是,我找不到任何带有注释的 Spring Boot 示例。

在我们的例子中,有一个中央 LDAP 存储库,其中存储了用户的用户名和密码,但用户组没有存储在那里。

我很欣赏任何示例或引用。 提前谢谢你。

最佳答案

您可以在下面找到我们在项目中的最终实现。 基本流程是:

a) 在验证过程中检查用户 ID 和角色。如果用户未定义或不具有应用程序的角色,则不要对用户进行身份验证。

b)如果用户通过了数据库检查,则继续进行ldap认证。

c) 将来自数据库的角色与 ldap 合并,以便在应用程序期间使用。

public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter implements InitializingBean {
...
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
  .authenticationProvider(this.ldapAndDatabaseAuthenticationProvider());
}

@Bean(name="ldapAuthenticationProvider")
public AuthenticationProvider ldapAndDatabaseAuthenticationProvider(){
  LdapUserDetailsMapper userDetailsMapper = new LdapUserDetailsMapper();
  userDetailsMapper.setRoleAttributes(new String[]{"groupMembership"});

  LdapAndDatabaseAuthenticationProvider provider = 
      new LdapAndDatabaseAuthenticationProvider(this.ldapAuthenticator(), this.ldapAuthoritiesPopulator());
  provider.setUserDetailsContextMapper(userDetailsMapper);

  return provider;
}

@Bean( name = "ldapAuthoritiesPopulator" )
public LdapAndDatabaseAuthoritiesPopulator ldapAuthoritiesPopulator(){
  return new LdapAndDatabaseAuthoritiesPopulator(this.contextSource(), "");
}

@Bean( name = "ldapAuthenticator" )
public LdapAuthenticator ldapAuthenticator() {

    BindAuthenticator authenticator = new BindAuthenticator(   this.contextSource() );
  authenticator.setUserDnPatterns(new String[]{"cn={0},ou=prod,o=COMP"});

  return authenticator;
}

@Bean( name = "contextSource" )
public DefaultSpringSecurityContextSource contextSource() {

    DefaultSpringSecurityContextSource contextSource =
          new DefaultSpringSecurityContextSource( ldapUrl );
    return contextSource;
}

以下是附加角色填充器 (LdapAndDatabaseAuthoritiesPopulator) 的实现方式。

public class LdapAndDatabaseAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator{

  public LdapAndDatabaseAuthoritiesPopulator(ContextSource contextSource, String groupSearchBase) {
    super(contextSource, groupSearchBase);
  }

  protected Set<GrantedAuthority> getAdditionalRoles(DirContextOperations user,
      String username) {
    Set<GrantedAuthority> mappedAuthorities = new HashSet<GrantedAuthority>();

    /* Add additional roles from other sources for this user*/
    /* below add is just an example of how to add a role */
    mappedAuthorities.add(
        new GrantedAuthority() { 
          private static final long serialVersionUID = 3618700057662135367L;

          @Override 
          public String getAuthority() { 
            return "ROLE_MYAPP_USER"; //this is just a temporary role we are adding as example. get the roles from database.
          } 

         @Override
         public String toString(){
          return this.getAuthority();
         }
        });


    for (GrantedAuthority granted : mappedAuthorities) {
      log.debug("Authority : {}", granted.getAuthority().toString());
    }

    return mappedAuthorities;
  }

}

下面是自定义 Ldap 身份验证提供程序 (LdapAndDatabaseAuthenticationProvider) 如何实现以检查用户是否具有在数据库中定义的访问应用程序所需的角色。如果用户不在数据库中或缺少角色,身份验证将抛出帐户 DisabledException。

franDays 还建议使用“Custom Authentication Provider”。我想称赞他。

public class LdapAndDatabaseAuthenticationProvider extends LdapAuthenticationProvider{

  public LdapAndDatabaseAuthenticationProvider(LdapAuthenticator authenticator, LdapAuthoritiesPopulator authoritiesPopulator) {
    super(authenticator, authoritiesPopulator);
  }

  @Override
  protected DirContextOperations doAuthentication(
      UsernamePasswordAuthenticationToken authentication) {

    log.debug("Checking if user <{}> is defined at database to use this application.", authentication.getName());

    // Here is the part we need to check in the database if user has required role to log into the application.
    // After check if user has the role, do nothing, otherwise throw exception like below example.    
    boolean canUserAuthenticate = isActiveUserExist(authentication.getName());
    log.debug("canUserAuthenticate: {}", canUserAuthenticate);

    if (!canUserAuthenticate)
      throw new DisabledException("User does not have access to Application!");

    return super.doAuthentication(authentication);
  }


  private boolean isActiveUserExist(String userId) {

  // Do your logic here are return boolean value...

  }

关于java - 具有 LDAP 身份验证的自定义权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37007445/

相关文章:

java - eclipse导入问题

java - 无法将 java.lang.String 类型的属性值转换为所需的类型 double

java - 如何使用注释在 Spring 中加载系统属性?

java - 如何在java中将消费者组添加到消息中?

grails - 创建对象时如何设置用户ID号的值?

java - 使用 Java API 在 Elasticsearch 中创建 MongoDB River

java - 我如何在 Java 中表示来自 C++ 的 numeric_limits?

spring - 如何在 Java 配置中使用 delegatingFilterproxy?

spring-mvc - 如何在SpringBootTest中向自动连线的testRestTemplate添加基本身份验证; Spring Boot 1.4

java - Spring 安全 : configuration error