2016-05-03 35 views
1

私は、LDAPでログインしてログインしたユーザの権限を、LDAPではなくカスタムメソッドの助けを借りて設定するためのSpring XML設定の例をほとんど見つけませんでした。 残念ながら、注釈付きのSpringブートの例は見つかりませんでした。LDAP認証のカスタム権限

この例では、ユーザーのユーザー名とパスワードが格納されている中央LDAPリポジトリがありますが、ユーザーのグループはそこに格納されていません。

いずれの例も参考になります。 ありがとうございます。

答えて

2

は、プロジェクトで私たちの最終的な実装を見つけることができます。 基本フロー:

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も「カスタム認証プロバイダ」の使用を推奨しています。私は彼に信用を与えたいと思います。

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... 

    } 
+0

私のアプリケーションでは、ロールとロールには特権があります。その場合は、mappedAuthoritiesメソッド(ロール名または特権名)でどのように割り当てる必要がありますか? –

1

独自のAuthenticationProviderを実装できます。 authenticateメソッドはLdapTemplateを照会し、試行が成功すると、グループがどこに格納されているか照会します。これは、以下のようになります。それはあなたのケースの仕様に依存するため

public class CustomAuthenticationProvider implements AuthenticationProvider { 

    private LdapTemplate ldapTemplate; 
    private UserRepository userRepository; 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     String username = (String) authentication.getPrincipal(); 
     boolean success = ldapTemplate.authenticate(...); 
     if (!success) { 
      throw new BadCredentialsException("Wrong username or password"); 
     } 
     User user = userRepository.findByUsername(username); 
     if (user == null) { 
      throw new BadCredentialsException("Username not known by the application"); 
     } 
     return new CustomAuthentication(username, user.getRoles()); 
    } 
} 

私はLdapTemplateの初期化を省略しました。クラスを実装し、ユーザー名とパスワードを渡してインスタンスを構築する方法が必要な場合に返すAuthenticationオブジェクトの場合と同じです。

あなたはJavaの設定を使用して、認証プロバイダを登録する方法についてのガイダンスが必要な場合は、この記事が役立つかもしれない:あなた以下Custom Authentication provider with Spring Security and Java Config