web-dev-qa-db-fra.com

Spring Boot avec UserDetailsService personnalisé

Quelle est la bonne façon d'ajouter mon implémentation personnalisée de UserDetailsService (qui utilise Spring Data JPA) à l'application Spring Boot?

public class DatabaseUserDetailsService implements UserDetailsService {

    @Inject
    private UserAccountService userAccountService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userAccountService.getUserByEmail(username);
        return new MyUserDetails(user);
    }

}


public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {

    public User findByEmail(String email);

}



@Service
public class UserAccountService {

    @Inject
    protected UserRepository userRepository;

    public User getUserByEmail(String email) {
        return userRepository.findByEmail(email);
    }

}


@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.sample")
@EntityScan(basePackages = { "com.sample" })
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    ...

    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/").hasRole("USER")
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
        }


    }

    @Order(Ordered.HIGHEST_PRECEDENCE + 10)
    protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {

        @Inject
        private UserAccountService userAccountService;

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService());
        }

        @Bean
        public UserDetailsService userDetailsService() {
            return new DatabaseUserDetailsService();
        }

    }

}


@Entity
public class User extends AbstractPersistable<Long> {

    @ManyToMany
    private List<Role> roles = new ArrayList<Role>();

    // getter, setter

}


@Entity
public class Role extends AbstractPersistable<Long> {

    @Column(nullable = false)
    private String authority;

    // getter, setter

}

Je ne peux pas démarrer l'application car je reçois (exception complète ici http://Pastebin.com/gM804mvQ )

Caused by: org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: com.sample.model.User.roles[com.sample.model.Role]
    at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.Java:1134)

Lorsque je configure mon ApplicationSecurity avec auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("...).authoritiesByUsernameQuery("...") tout fonctionne, y compris les référentiels JPA et Spring Data.

18
igo

Votre application semble fonctionner pour moi (une fois que j'ai ajouté @Configuration au AuthenticationSecurity). Voici un autre exemple de travail d'une application simple avec JPA UserDetailsService au cas où cela aiderait: https://github.com/scratches/jpa-method-security-sample

10
Dave Syer

Vous pouvez également suivre ce blog pour implémenter un service de détails utilisateur personnalisé.

Cet exemple montre comment envoyer un bean au service userdetails pour l'injection.

  1. Câblage automatique du référentiel dans WebSecurityConfigurer
  2. Envoyez ce bean en tant que paramètre au service de détails utilisateur par un constructeur paramétré.
  3. attribuez-lui un membre privé et utilisez-le pour charger les utilisateurs à partir de la base de données.
4
Ekansh Rastogi