Spring security switch to Ldap authentication and database authorities

后端 未结 4 430
灰色年华
灰色年华 2020-12-08 01:34

I implemented database authentication for my web page and web service. It work well for both, now I have to add Ldap authentication. I have to authenticate through remote L

相关标签:
4条回答
  • 2020-12-08 01:49

    For anyone using grails it is much simpler. Simply add this to your config:

    grails: plugin: springsecurity: ldap: authorities: retrieveDatabaseRoles: true

    0 讨论(0)
  • 2020-12-08 01:54

    Spring Security already supports LDAP out-of-the-box. It actually has a whole chapter on this.

    To use and configure LDAP add the spring-security-ldap dependency and next use the AuthenticationManagerBuilder.ldapAuthentication to configure it. The LdapAuthenticationProviderConfigurer allows you to set the needed things up.

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.ldapAuthentication()
          .contextSource()
            .url(...)
            .port(...)
            .managerDn(...)
            .managerPassword(...)
          .and()
            .passwordEncoder(passwordEncoder())
            .userSearchBase(...)        
            .ldapAuthoritiesPopulator(new UserServiceLdapAuthoritiesPopulater(this.userService));      
    }
    

    Something like that (it should give you at least an idea on what/how to configure things) there are more options but check the javadocs for that. If you cannot use the UserService as is to retrieve the roles (because only the roles are in the database) then implement your own LdapAuthoritiesPopulator for that.

    0 讨论(0)
  • 2020-12-08 01:54

    You need to create a CustomAuthenticationProvider wich implements AuthenticationProvider, and override authenticate method, for example:

    @Component
    public class CustomAuthenticationProvider
        implements AuthenticationProvider {
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = authentication.getName();
            String password = authentication.getCredentials().toString();
    
            boolean authenticated = false;
            /**
             * Here implements the LDAP authentication
             * and return authenticated for example
             */
            if (authenticated) {
    
                String usernameInDB = "";
                /**
                 * Here look for username in your database!
                 * 
                 */
                List<GrantedAuthority> grantedAuths = new ArrayList<>();
                grantedAuths.add(new     SimpleGrantedAuthority("ROLE_USER"));
                Authentication auth = new     UsernamePasswordAuthenticationToken(usernameInDB, password,     grantedAuths);
                return auth;
            } else {
                return null;
            }
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return     authentication.equals(UsernamePasswordAuthenticationToken.class);
        }
    
    }
    

    Then, in your SecurityConfig, you need to override the configure thats use AuthenticationManagerBuilder:

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(this.authenticationProvider);
    }
    

    You can autowire the CustomAuthenticationProvider doing this:

    @Autowired
    private CustomAuthenticationProvider authenticationProvider;
    

    Doing this, you can override the default authentication behaviour.

    0 讨论(0)
  • 2020-12-08 02:00

    I also found this chapter Spring Docu Custom Authenicator and build my own switch between LDAP and my DB users. I can effortlessy switch between login data with set priorities (in my case LDAP wins).

    I have configured an LDAP with the yaml configuration files for the LDAP user data which I don't disclose here in detail. This can be easily done with this Spring Docu LDAP Configuration.

    I stripped the following example off the clatter such as logger/javadoc etc. to highlight the important parts. The @Order annotation determines the priorities in which the login data is used. The in memory details are hardcoded debug users for dev only purposes.

    SecurityWebConfiguration

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
      @Inject
      private Environment env;
      @Inject
      private LdapConfiguration ldapConfiguration;
    
      @Inject
      private BaseLdapPathContextSource contextSource;
      @Inject
      private UserDetailsContextMapper userDetailsContextMapper;
    
      @Inject
      private DBAuthenticationProvider dbLogin;
    
      @Inject
      @Order(10) // the lowest number wins and is used first
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new InMemoryUserDetailsManager(getInMemoryUserDetails()));
      }
    
      @Inject
      @Order(11) // the lowest number wins and is used first
      public void configureLDAP(AuthenticationManagerBuilder auth) throws Exception {
        if (ldapConfiguration.isLdapEnabled()) {
          auth.ldapAuthentication().userSearchBase(ldapConfiguration.getUserSearchBase())
              .userSearchFilter(ldapConfiguration.getUserSearchFilter())
              .groupSearchBase(ldapConfiguration.getGroupSearchBase()).contextSource(contextSource)
              .userDetailsContextMapper(userDetailsContextMapper);
        }
      }
    
      @Inject
      @Order(12) // the lowest number wins and is used first
      public void configureDB(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(dbLogin);
      }
    }
    

    DB Authenticator

    @Component
    public class DBAuthenticationProvider implements AuthenticationProvider {
    
      @Override
      public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String name = authentication.getName();
        String password = authentication.getCredentials().toString();
    
       // your code to compare to your DB
      }
    
      @Override
      public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
      }
    
      /**
       * @param original <i>mandatory</i> - input to be hashed with SHA256 and HEX encoding
       * @return the hashed input
       */
      private String sha256(String original) {
        MessageDigest md = null;
        try {
          md = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
          throw new AuthException("The processing of your password failed. Contact support.");
        }
    
        if (false == Strings.isNullOrEmpty(original)) {
          md.update(original.getBytes());
        }
    
        byte[] digest = md.digest();
        return new String(Hex.encodeHexString(digest));
      }
    
      private class AuthException extends AuthenticationException {
        public AuthException(final String msg) {
          super(msg);
        }
      }
    }
    

    Feel free to ask details. I hope this is useful for someone else :D

    0 讨论(0)
提交回复
热议问题