必须在Spring Boot应用中将UserDetailsS​​ervice设置为错误

时间:2019-07-15 14:32:08

标签: spring spring-boot spring-security

我有2个课程

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private UserDetailServiceImpl   customUserDetailsService;


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}

}

和UserDetailsS​​erviceImpl

@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
private UserRepository repository;

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

    UserDetails user = new org.springframework.security.core.userdetails.User(
            username,
            currentUser.getPassword(),
            true,
            true,
            true,
            true,
            AuthorityUtils.createAuthorityList(currentUser.getRole()));
    return user;
}

}

日志错误:

Caused by: java.lang.IllegalArgumentException: A UserDetailsService must be set
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.doAfterPropertiesSet(DaoAuthenticationProvider.java:100)

来自docs的错误可能来自于此:

 Throws:IllegalArgumentException - if a null value was passed either as a parameter or as an element in the GrantedAuthority collection

属性设置不正确可能... 那么如何设置UserDetailsS​​ervice呢?如何解决此错误?这个例子是从书中摘下来的,但是它可能太旧了,有些东西改变了。我是Spring的新手。

2 个答案:

答案 0 :(得分:2)

所以我可以使用以下方法解决此问题:

对于SecurityConfig.java:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private UserDetailServiceImpl customUserDetailsService;

    //Spring injecting for you, IoC
    public SecurityConfig(UserDetailServiceImpl customUserDetailsService) {
        this.customUserDetailsService = customUserDetailsService;
    }


    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService)
            .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable() //We don't need CSRF for this example
            .authorizeRequests()
            .anyRequest().authenticated() // all request requires a logged in user
            .and()
            .formLogin()
            .loginProcessingUrl("/login") //the URL on which the clients should post the login information
            .usernameParameter("username") //the username parameter in the queryString, default is 'username'
            .passwordParameter("password");
    }
}

在这里,您可以配置要求登录的URL,如果您想自定义登录URL,用户名和密码字段,请配置表单。

您的主要问题是,您没有在类中注入“ UserDetailServiceImpl”。

这里的提示:您可以像上面一样使用@Autowired构造函数,并且弹簧将为您注入,因此您不必使用注释。

这是创建单元测试之后的好方法,并且在构造要测试的类时可以轻松地进行模拟。

答案 1 :(得分:0)

我用了这个答案,对我有用:

https://stackoverflow.com/a/42191609/1010619

@EnableWebSecurity
@Configuration
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    private UserDetailsService userDetailsService;

public AppSecurityConfig(UserDetailsService userDetailsService) {
    super();
    this.userDetailsService = userDetailsService;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder builder, PasswordEncoder passwordEncoder) throws Exception {
    builder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    // @formatter:off
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/webjars/**", "/static/**").permitAll()
            .antMatchers("/", "/index", "/home", "/register", "/user/confirmRegistration").permitAll()
            .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/loginCustom").permitAll().loginProcessingUrl("/doLogin")
            .and()
            .logout().permitAll().logoutUrl("/logout").logoutSuccessUrl("/")
            .and()
            .csrf().disable()
            ;
    }// @formatter:on 

    public UserDetailsService getUserDetailsService() {
    return userDetailsService;
    }

    @Autowired
    public void setUserDetailsService(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
    }

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

}