Spring Boot - аутентификация через локальную БД или Active Directory в зависимости от флага - PullRequest
0 голосов
/ 03 января 2019

Я недавно разработал приложение Spring Boot и использую локальную базу данных для аутентификации пользователя.

Теперь, поскольку приложение используется все больше и больше, я также хочу включить аутентификацию через активный каталог моей компании.

Я все еще хочу сохранить всех пользователей в моей локальной таблице пользователей, чтобы они ссылались на них из других таблиц, но для некоторых пользователей сверяем имя пользователя и пароль с активным каталогом. Является ли пользователь активным пользователем каталога или локальным пользователем, хранится в таблице пользователей.

В псевдокоде это будет выглядеть примерно так:

if(user.isAdUser()) {
    checkCredentialsAgainstAD();
} else {
    checkCredentialsAgainstLocalDb();
}

Мой текущий код аутентификации выглядит так:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDAO userDao;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /* http.authorizeRequests()... */
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(new CustomUserDetailsService(userDao)).passwordEncoder(new BCryptPasswordEncoder());
    }
}

и загружает пользовательскую информацию из базы данных через userDao в переопределенном методе loadUserByUsername(String username):

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = userDao.readUserByLogin(username, true);

    if(user == null){
        log.info(username + " not found");
        throw new UsernameNotFoundException(username + " not found");
    }

    User userObj = user.clone();
    userObj.password = null;

    return new CustomUserDetails(user.loginName, user.password, getAuthorities(user), userObj);
}

Я уже понял, что могу добавить ActiveDirectoryLdapAuthenticationProvider вот так

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(new ActiveDirectoryLdapAuthenticationProvider("DOMAIN", "ldap://example.com")).userDetailsService(new CustomUserDetailsService(userDao)).passwordEncoder(new BCryptPasswordEncoder());
})

Но это всегда будет использовать активный каталог.

Как конкретно выбрать, какой поставщик аутентификации будет использоваться?

Я не хочу тестировать всех провайдеров в порядке, предложенном в Конфигурация Java Spring Security - несколько провайдеров аутентификации , но только правильный, в зависимости от флага, который я получаю из базы данных.

1 Ответ

0 голосов
/ 03 января 2019

Основываясь на ваших требованиях, я думаю, что, возможно, самое простое решение - создать ваш пользовательский AuthenticationProvider, который внутренне обернет DaoAuthenticationProvider и ActiveDirectoryLdapAuthenticationProvider.

Только этот пользовательский AuthenticationProvider будет зарегистрирован. Во время аутентификации вы сначала получаете пользователя из БД, чтобы определить его «режим аутентификации» и делегируете DaoAuthenticationProvider или ActiveDirectoryLdapAuthenticationProvider соответственно для дальнейшей аутентификации.

Что-то вроде ниже, не стесняйтесь изменять:

@Service
public class MyCustomAuthenticationProvider implements AuthenticationProvider{

        @Autowired
        private DaoAuthenticationProvider dbAuthProvider;

        @Autowired
        private ActiveDirectoryLdapAuthenticationProvider adAuthProvider;

        @Autowired
        UserDAO userDao;

        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException{

            // Determine username
            String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED": authentication.getName();
            User user = userDao.getUserByName(username);
            if(user == null){
                throw new  AuthenticationException("Sorry. No this user.");
            }

            if(user.isAdUser()) {
                return adAuthProvider.authenticate(authentication);
            } else {
               return dbAuthProvider.authenticate(authentication);
            }

        }

        @Override
        public boolean supports(Class<?> authentication){
            return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
        }


}

Но как связать их с помощью аннотированной конфигурации - это еще одна история, которую необходимо продолжить .....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...