Настройка UserDetails с использованием службы без LoadTimeWeaving

Мне нужно использовать список объектов для контроля доступа. Запрос для получения этого списка довольно сложный и длинный, поэтому я хотел бы кэшировать его в объекте пользователя, когда пользователь проходит аутентификацию на сервере. Я решил попытаться решить эту проблему с помощью настраиваемой реализации UserDetailService и этого WebSecurityConfig:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

...


        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            String ldapURI = "ldap://" + ldaHost + ":" + ldapPort + "/" + ldapBasis;

            DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURI);
            contextSource.setUserDn(ldapUser);
            contextSource.setPassword(ldapPassword);
            contextSource.afterPropertiesSet();

            LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth
                    .ldapAuthentication().userDetailsContextMapper(new LdapUserDetailsContextMapper());

            ldapAuthenticationProviderConfigurer
                    .userSearchFilter("(&(criteria={0}))")
                    .userSearchBase("ou=usersearchbase").contextSource(contextSource);
        }
}

ContextMapper для заполнения пользовательского объекта данными:

public class LdapUserDetailsContextMapper implements UserDetailsContextMapper {

private final org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());

private DataService dataService;

public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
                                      Collection<? extends GrantedAuthority> authorities) {

    AppUser user = new AppUser();
    user.setUsername(ctx.getStringAttribute("uid"));
    user.setName(ctx.getStringAttribute("cn"));
    user.setSurname(ctx.getStringAttribute("sn"));
    user.setMail(ctx.getStringAttribute("mail"));
    user.setRoleUser();    

user.setManaged(dataService.getManagedData(user.getMail()));

                    return user;
                }

Проблема в том, что я не вижу способа внедрить мой DataService в этот процесс - ни ContextMapper, ни класс @Configure не являются управляемыми компонентами, что делает невозможным @Autowired. Я хочу избежать LoadTimeWeaving, потому что использование этого очень усложнит развертывание - есть ли у меня другой выбор?

Я обнаружил две похожие проблемы: почему мое поле Spring @Autowired пусто? имеет ту же проблему в классе Controller, который можно превратить в управляемый компонент; оба других упомянутых решения не работали для меня (dataService всегда был нулевым) и Spring Boot, @Autowire, в неуправляемый класс с использованием @Configurable и переплетения времени загрузки снова рекомендует LoadTimeWeaving.

Я также нашел очевидные решения, в которых упоминается использование @Autowired в методе init, но я также не смог заставить его работать (пытаясь вызвать ContextMapper-конструктор с внедренным dataService)

1 ответ

Решение

Просто сделайте это бобом с пружиной.

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

...


        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            String ldapURI = "ldap://" + ldaHost + ":" + ldapPort + "/" + ldapBasis;

            DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(ldapURI);
            contextSource.setUserDn(ldapUser);
            contextSource.setPassword(ldapPassword);
            contextSource.afterPropertiesSet();

            LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthenticationProviderConfigurer = auth
                    .ldapAuthentication().userDetailsContextMapper(userDetailsContextMapper());

            ldapAuthenticationProviderConfigurer
                    .userSearchFilter("(&(criteria={0}))")
                    .userSearchBase("ou=usersearchbase").contextSource(contextSource);
        }
    @Bean
    public LdapUserDetailsContextMapper userDetailsContextMapper() {
        return new LdapUserDetailsContextMapper();
    }
}

И аннотируйте свое поле внутри LdapUserDetailsContextMapper с @Autowired,

Другие вопросы по тегам