【问题标题】:Spring Boot with custom UserDetailsService带有自定义 UserDetailsS​​ervice 的 Spring Boot
【发布时间】:2014-09-03 13:58:53
【问题描述】:

将我的 UserDetailsS​​ervice(使用 Spring Data JPA)的自定义实现添加到 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

}

我无法启动应用程序,因为我得到了(这里是完全例外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)

当我用auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("...).authoritiesByUsernameQuery("...") 配置我的ApplicationSecurity 时,一切正常,包括JPA 和Spring Data 存储库。

【问题讨论】:

  • 问题在于 JPA 映射。请添加用户和角色实体(类)。
  • 已添加实体。无论如何,我认为实体没有问题,因为没有我的 UserDetailsS​​ervice,JPA 可以正常工作。
  • 不过我认为 Evgeni 是对的。该错误是映射错误。也许你可以分享一个完整的项目?
  • @DaveSyer,我在这里尝试将其最小化github.com/igo/spring-boot-userdetails。仍然无法运行,但是我遇到了另一个异常 NPE - DatabaseUserDetailsS​​ervice 中的 UserAccountService 为空。请尝试,您可能知道如何使用自定义 UserDetailsS​​ervice :)
  • 您的应用似乎对我有用(一旦我将 @Configuration 添加到 AuthenticationSecurity)。我该如何打破它?

标签: java spring spring-security spring-data spring-boot


【解决方案1】:

您的应用似乎对我有用(一旦我将@Configuration 添加到AuthenticationSecurity)。这是另一个使用 JPA UserDetailsService 的简单应用程序的工作示例,以防万一:https://github.com/scratches/jpa-method-security-sample

【讨论】:

  • 谢谢,这有助于前进。但现在我得到o.s.s.w.a.www.BasicAuthenticationFilter : Authentication request for failed: org.springframework.security.authentication.InternalAuthenticationServiceException: failed to lazily initialize a collection of role: com.sample.model.User.roles, could not initialize proxy - no Session。然而,我没有找到任何加载延迟获取角色的示例。我更新了我的 github 示例。
  • 懒惰的角色听起来是个坏主意(您总是需要在身份验证后检查授权),但这看起来就像您没有交易一样。也许UserDetailsService 疖子是事务性的加载角色,用一块石头杀死两只鸟,就像它一样?
  • @DaveSyer 你好,我不明白你的意思。我和 OP (failed to lazily initialize a collection of role) 有同样的错误。我是否必须将fetch=FetchType.EAGER 添加到com.sample.model.User.roles 或者是否有不那么繁重的方法?谢谢!
  • 理想情况下,您不应将 JPA 用于用户详细信息。如果您必须然后获取UserDetailsService 中的角色(并使其具有事务性)。
【解决方案2】:

您也可以关注this blog实现自定义用户详情服务。

这个例子展示了如何将 bean 发送到 userdetails 服务进行注入。

  1. 在 WebSecurityConfigurer 中自动装配存储库
  2. 通过参数化构造函数将此 bean 作为参数发送到用户详细信息服务。
  3. 为此分配一个私有成员并用于从数据库加载用户。

【讨论】:

    猜你喜欢
    • 2017-09-07
    • 2013-02-11
    • 2013-05-12
    • 1970-01-01
    • 2019-06-01
    • 2015-04-07
    • 2014-10-12
    • 2017-01-31
    • 2012-12-13
    相关资源
    最近更新 更多