如何为多个身份验证提供者提供spring security的java配置

如何为多个身份验证提供者提供spring security的java配置,java,spring,spring-mvc,spring-security,Java,Spring,Spring Mvc,Spring Security,我将有关用户的信息存储在单独的表中—所有者、员工、我试图在SpringSecurity中使用java配置的用户 我为每种用户类型创建了三个不同的身份验证提供程序,但只触发了用户提供程序。我已经阅读了spring安全文档,实现这一点的唯一方法似乎是使用WebSecurityConfigureAdapter扩展的多个嵌入式类创建类,但我不想这样做,因为它需要大量重复代码,还有其他方法吗 我尝试使用简单的userDetailService,在该服务中,我向Database中的所有表发送请求,但仍然没有

我将有关用户的信息存储在单独的表中—所有者、员工、我试图在SpringSecurity中使用java配置的用户

我为每种用户类型创建了三个不同的身份验证提供程序,但只触发了用户提供程序。我已经阅读了spring安全文档,实现这一点的唯一方法似乎是使用WebSecurityConfigureAdapter扩展的多个嵌入式类创建类,但我不想这样做,因为它需要大量重复代码,还有其他方法吗

我尝试使用简单的userDetailService,在该服务中,我向Database中的所有表发送请求,但仍然没有结果,只生成了一个查询,什么也没有执行,我得到的唯一响应是:

2016-02-09 23:06:25.976调试8780---[nio-8080-exec-1] .s.a.DefaultAuthenticationEventPublisher:找不到用于 例外 org.springframework.security.authentication.InternalAuthenticationServiceException

2016-02-09 23:06:25.976调试8780---[nio-8080-exec-1] o、 s.s.w.a.www.BasicAuthenticationFilter:的身份验证请求 失败: org.springframework.security.authentication.InternalAuthenticationServiceException: 未找到要查询的实体;嵌套异常是 javax.persistence.NoResultException:未找到用于查询的实体

但我从不抛出任何例外!!最奇怪的是,我可以在调试器中看到执行如何在em.createQuery(..).getSingleResult()之后快速停止。。就这样,没别的了!没有返回语句,没有异常,什么都没有,wtf

这是我当前配置的一部分:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .authenticationProvider(createAuthenticationProvider(employeeDetailService()))
            .authenticationProvider(createAuthenticationProvider(ownerDetailsService()))
            .authenticationProvider(createAuthenticationProvider(userDetailsService()));
}
 @Bean
    public OwnerDetailsService ownerDetailsService() {
        return new OwnerDetailsService();
    }

    @Bean
    public EmployeeDetailServiceImpl employeeDetailService() {
        return new EmployeeDetailServiceImpl();
    }

    @Bean
    public UserDetailsServiceImpl userDetailsService() {
        return new UserDetailsServiceImpl();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(6);
    }

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return new MySimpleUrlAuthenticationSuccessHendler();
    }



    private AuthenticationProvider createAuthenticationProvider(UserDetailsService service) {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setUserDetailsService(service);
    provider.setPasswordEncoder(passwordEncoder());
    provider.setHideUserNotFoundExceptions(true);
    return provider;
}
用户详细信息服务:

  @Service
    public abstract class CustomUserDetailService implements UserDetailsService{

        @Autowired
        IDBBean dao;

        protected CustomUserDetails getUser(GetUserByNameFunction function, String name) {
            return createUser(function.get(name));
        }

        protected CustomUserDetails createUser(Authenticational user) {
            return new CustomUserDetails(user, getAuthorities(user.getAuthority()));
        }

        protected List<GrantedAuthority> getAuthorities(String authority) {
            return Collections.singletonList(new SimpleGrantedAuthority(authority));
        }
    }
自定义用户详细信息:

private Long id;
    private String userEmail;


    public CustomUserDetails(Authenticational user,
                             Collection<? extends GrantedAuthority> authorities) {
        super(
                user.getName(),
                user.getPassword().toLowerCase(),
                user.isEnabled(),
                true,
                true,
                true,
                authorities);
        upadateValues(user);
    }

    private void upadateValues(Authenticational user) {
        this.id = user.getId();
        this.userEmail = user.getEmail();
    }
私有长id;
私人字符串用户电子邮件;
公共CustomUserDetails(身份验证用户,

如果提供程序引发
AccountStatusException
UserDetailsService
引发
UserNameNotFoundException
或任何其他
AuthenticationException

如果希望尝试其他提供程序,则
UserDetailsServiceImpl
OwnerDetailsService
loadUserByUserName
方法不应引发
UserNameNotFound
异常


您应该决定是否要返回一个虚拟的匿名
UserDetails
对象,该对象将专门用于回退,或者当用户在您的
UserDetails服务
实现中不可用时,使用其他机制不引发异常,只是为了从另一个答案中澄清一些问题:

您的身份验证提供程序存储在ProviderManager中的一个列表中,该列表通过它们迭代您的身份验证请求。如果您的身份验证提供程序引发AuthenticationException(BadCredentialsException扩展了AuthenticationException),则ProviderManager将尝试另一个提供程序。如果设置了hideUserNotFoundExceptions属性,则它也将包装并忽略UsernameNotFoundException,并在这种情况下尝试另一个提供程序

如果我是你,我会首先在ProviderManager的authenticate方法中放置一个调试点。从那里你可以了解为什么其他身份验证提供程序没有被调用来获取他们的authenticate方法


另外,我会考虑只有一个身份验证提供程序和一个UserDetailsService。在我看来,您正在做很多复杂的、实际上并不需要的操作,比如将函数传递给抽象实现,而您所能做的只是拥有一个UserDetailsService,它将向所有DAO请求一个用户。这就是basica这是你想要完成的,但是减去2个身份验证提供程序,减去1个抽象类,减去2个用户详细信息服务实现。

是的,非常感谢,你的回答真的很有帮助。我知道这有点太多了,但我才开始学习这个框架,现在正在尝试所有东西。很乐意帮助。我自己也是明星几个月前,ted与spring boot、security、oauth sso、data等进行了合作,所以我知道最初的痛苦。
private Long id;
    private String userEmail;


    public CustomUserDetails(Authenticational user,
                             Collection<? extends GrantedAuthority> authorities) {
        super(
                user.getName(),
                user.getPassword().toLowerCase(),
                user.isEnabled(),
                true,
                true,
                true,
                authorities);
        upadateValues(user);
    }

    private void upadateValues(Authenticational user) {
        this.id = user.getId();
        this.userEmail = user.getEmail();
    }