繁体   English   中英

Bean Cycle Spring 安全

[英]Bean Cycle Spring Security

我正在开发一个 Spring 引导 web 应用程序。 问题出在登录场景中,并且 ima 堆积在循环中。 写道依赖关系是相互关联的,我无法弄清楚究竟是如何以及为什么

描述:

application context中的一些bean的依赖关系形成了一个循环:

┌─────┐
|  webSecurityConfig (field boot.service.UserDetailsServiceImpl boot.configs.WebSecurityConfig.userDetailsService)
↑     ↓
|  userDetailsServiceImpl (field org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder boot.service.UserDetailsServiceImpl.bCryptPasswordEncoder)
└─────┘

我该如何解决这个问题,伙计们? 我的课程:

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @PersistenceContext
    private EntityManager em;

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }

        return user;
    }

    public User findUserById(Long userId) {
        Optional<User> userFromDb = userRepository.findById(userId);
        return userFromDb.orElse(new User());
    }

    public List<User> allUsers() {
        return userRepository.findAll();
    }

    public boolean saveUser(User user) {
        User userFromDB = userRepository.findByUsername(user.getUsername());

        if (userFromDB != null) {
            return false;
        }

        user.setRoles(Collections.singleton(new Role(1L, "ROLE_User")));
        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
        userRepository.save(user);
        return true;
    }

    public boolean deleteUser(Long userId) {
        if (userRepository.findById(userId).isPresent()) {
            userRepository.deleteById(userId);
            return true;
        }
        return false;
    }

    public List<User> usergtList(Long idMin) {
        return em.createQuery("SELECT u from User u WHERE u.id > :paramId", User.class)
                .setParameter("paramId", idMin).getResultList();
    }


}

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf()
                    .disable()
                .authorizeRequests()
                    .antMatchers("/registration").not().fullyAuthenticated()
                    .antMatchers(("/admin/**")).hasRole("ADMIN")
                    .antMatchers("/", "/resources/**").permitAll()
                .anyRequest().authenticated()
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .defaultSuccessUrl("/")
                    .permitAll()
                .and()
                    .logout()
                    .permitAll()
                    .logoutSuccessUrl("/");
    }

    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }
}

帮我弄清楚,我的脑袋已经坏了,谷歌也帮不上忙

如果您从 Spring 阅读UserDetailsService ervice 接口的 javadoc - 实现的责任应该是“加载用户数据”。

您实施的问题在于您打算将其用于更多目的,即“节省用户”。 要保存用户,您的UserDetailsService ervice 还依赖于WebSecurityConfig中提供的PasswordEncoder bean,但是为了提供一个UserDetailsService ervice 是必需的 - 这就是那个循环。

这表明设计中存在错误,应该以某种方式进行重构。

打破这个循环的最简单方法是允许延迟注入PasswordEncoder ,方法是在UserDetailsServiceImpl erviceImpl class 中用@Lazy注释它——但我不建议这样做。 它会让你摆脱这种情况,但糟糕的设计选择不会得到纠正。

我建议将loadUserByUsername实现以外的所有逻辑从UserDetailsServiceImpl移到其他一些@Service (即UserService )中。 - 这样你就会尊重 Spring 的UserDetailsService接口中定义的契约,并且你的UserDetailsServiceImpl将不会依赖于PasswordEncoder bean - 因此你的循环依赖将被删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM