Java Spring Security能否为同一用户接受多个密码?

Java Spring Security能否为同一用户接受多个密码?,java,spring-security,Java,Spring Security,我在我的应用程序中使用Spring安全机制,用一个密码对用户进行身份验证。我试图满足一个要求,即覆盖密码也将对同一用户进行身份验证 如何使用Spring Security实现这一点?有可能,您必须通过扩展现有的DAAuthenticationProvider来实现自己的AuthenticationProvider(请参见此处的additionalAuthenticationChecks()。 此外,默认情况下,该用户仅与一个密码关联(UserDetails.getPassword()),因此您需

我在我的应用程序中使用Spring安全机制,用一个密码对用户进行身份验证。我试图满足一个要求,即覆盖密码也将对同一用户进行身份验证


如何使用Spring Security实现这一点?

有可能,您必须通过扩展现有的
DAAuthenticationProvider
来实现自己的
AuthenticationProvider
(请参见此处的
additionalAuthenticationChecks()


此外,默认情况下,该用户仅与一个密码关联(
UserDetails.getPassword()
),因此您需要该类的一个扩展来保存多个密码,以及一个相应的
UserDetailsService
实现,该实现知道如何加载用户及其密码

通过提供多个带有“UserDetailsService”的“AuthenticationProvider”,很容易做到这一点

private DaoAuthenticationProvider userAuthProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setHideUserNotFoundExceptions(false);    
    provider.setPasswordEncoder(passwordEncoder);
    provider.setUserDetailsService(userDetailsService);
    return provider;
}

private DaoAuthenticationProvider superVisorAuthProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setHideUserNotFoundExceptions(false);
    provider.setUserDetailsService(supervisorDetailService);
    return provider;
}
然后


如前所述,您可以覆盖“additionalAuthenticationChecks” 希望这对别人有帮助

@Slf4j
@Service
class FlexibleAuthenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    UserDetailsService userDetailsService

    @Autowired
    PasswordEncoder passwordEncoder

    @PostConstruct
    def init() {
        super.setPasswordEncoder(passwordEncoder)
        super.setUserDetailsService(userDetailsService)
    }

    @Override
    protected void additionalAuthenticationChecks(
            UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        try {
            super.additionalAuthenticationChecks(userDetails, authentication)
        } catch (AuthenticationException e) {
            log.error('Unable to authenticate with regular credentials')
           
            try {
                def mutableUserDetails = new MutableUser(userDetails)
                mutableUserDetails.password = 'alternatepassword'
                return super.additionalAuthenticationChecks(mutableUserDetails, authentication)
            } catch (AuthenticationException err) {
                log.error('Token based authentication failed')
            }
            
            throw e
        }
    }
    
    static class MutableUser implements UserDetails {

        private String password
        private final UserDetails delegate

        MutableUser(UserDetails user) {
            this.delegate = user
            this.password = user.password
        }

        String getPassword() {
            return password
        }

        void setPassword(String password) {
            this.password = password
        }

        ....

    }


}







@Configuration
class AuthWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    FlexibleAuthenticationProvider flexibleAuthenticationProvider

    ....

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(flexibleAuthenticationProvider)
    }

    ....

}

我实现了自己的AuthenticationProvider,并在重写的authenticate()方法中执行了所需的工作。谢谢你的帮助!有没有关于如何做到这一点的例子?
@Slf4j
@Service
class FlexibleAuthenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    UserDetailsService userDetailsService

    @Autowired
    PasswordEncoder passwordEncoder

    @PostConstruct
    def init() {
        super.setPasswordEncoder(passwordEncoder)
        super.setUserDetailsService(userDetailsService)
    }

    @Override
    protected void additionalAuthenticationChecks(
            UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        try {
            super.additionalAuthenticationChecks(userDetails, authentication)
        } catch (AuthenticationException e) {
            log.error('Unable to authenticate with regular credentials')
           
            try {
                def mutableUserDetails = new MutableUser(userDetails)
                mutableUserDetails.password = 'alternatepassword'
                return super.additionalAuthenticationChecks(mutableUserDetails, authentication)
            } catch (AuthenticationException err) {
                log.error('Token based authentication failed')
            }
            
            throw e
        }
    }
    
    static class MutableUser implements UserDetails {

        private String password
        private final UserDetails delegate

        MutableUser(UserDetails user) {
            this.delegate = user
            this.password = user.password
        }

        String getPassword() {
            return password
        }

        void setPassword(String password) {
            this.password = password
        }

        ....

    }


}







@Configuration
class AuthWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    FlexibleAuthenticationProvider flexibleAuthenticationProvider

    ....

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(flexibleAuthenticationProvider)
    }

    ....

}