Java 无法自动关联WebSecurity配置适配器的字段

Java 无法自动关联WebSecurity配置适配器的字段,java,spring,spring-boot,hibernate,autowired,Java,Spring,Spring Boot,Hibernate,Autowired,这是我对WebSecurity配置适配器的实现: import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authenticatio

这是我对WebSecurity配置适配器的实现:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
  @Autowired
  private JWTUserDetailsService jwtUserDetailsService;
  @Autowired
  private JWTRequestFilter jwtRequestFilter;

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

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Bean
  public JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint() {
    return new JWTAuthenticationEntryPoint();
  }

  @Bean
  public JWTUserDetailsService jwtUserDetailsService() {
    return new JWTUserDetailsService();
  }



  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    Implementation omitted

  }

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    implementation omitted
  }
}

这是我对用户详细信息服务的实现:

import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import tidbit.models.Reader;
import tidbit.models.ReaderRepository;

@Component
public class JWTUserDetailsService implements UserDetailsService {
  @Autowired private ReaderRepository<Reader> repository;

  public JWTUserDetailsService() {
    super();
  }

  @Override
  public UserDetails loadUserByUsername(String username) {
   Implementation omitted
  }
}
在WebSecurityConfig类中,我发现所有字段都有一个错误,表示Spring无法自动连接这些字段:

无法自动连线。未找到“JWTRequestFilter”的bean

通过创建这两个用
@Bean
注释的方法,我能够解决前两个字段的这个问题。 但是,我不知道如何为RequestFilter解决它,因为它包含一个构造函数,其中的参数在技术上应该已经自动连接

总的来说,我认为我一开始就不应该犯这个错误。我在网上看过一些教程,它们能够自动关联这些字段,没有任何问题,也没有创建任何@bean方法

编辑:

感谢您的帮助:

现在我得到以下错误

tidbit.controllers.AuthenticationController中构造函数的参数3需要一个bean,但找到了2个: -JWTUserDetailsService:在文件[/Users/matteoomenetti/Documents/TidBit/backend/build/classes/java/main/TidBit/config/JWTUserDetailsService.class]中定义 -jwtUserDetailsService:由类路径资源[tidbit/config/WebSecurityConfig.class]中的方法“jwtUserDetailsService”定义

看起来我正在创建两个jwtUserDetailService bean。一个已经在jwtUserDetailService中定义,另一个在WebSecurityConfig中使用@bean注释定义。然而,如果我在jwtUserDetailService中已经有一个bean,为什么WebSecurity配置找不到它

我已经注意到,如果我尝试在任何其他类(没有我创建的bean方法)中自动连接jwtUserDetailService,它可以完美地工作,这意味着找到了bean。由于某些原因,我的WebSecurity配置类找不到bean

解决方案

我得到的错误只是IntelliJ的错误。如果我试图通过终端进行编译,我不会得到任何错误


谢谢大家

我建议您停止使用
new
关键字来实例化bean。修改以下方法:

  @Bean
  public JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint() {
    return jwtAuthenticationEntryPoint;
  }

  @Bean
  public JWTUserDetailsService jwtUserDetailsService() {
    return jwtUserDetailsService;
  }
此外,还可以修改以下类,如下所示:

@Component
public class JWTRequestFilter extends OncePerRequestFilter {
 @Autowired
  private final JWTUserDetailsService jwtUserDetailsService;
 @Autowired
  private final JWTTokenUtils jwtTokenUtils;

 
  public JWTRequestFilter() {
  }

  @Override
  protected void doFilterInternal(
     Implementation omitted
  }
}

除了
AuthenticationManager
PasswordEncoder
之外,您不应该创建新的
@Bean

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
  
  @Autowired
  private JWTUserDetailsService jwtUserDetailsService;
  
  @Autowired
  private JWTRequestFilter jwtRequestFilter;
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //authorizeRequests() order is important
        http
        .csrf().disable()
        .authorizeRequests().antMatchers("/**").authenticated()
        .and()
        .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint); 
    }
    
    @Override
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
    @Bean
    public DaoAuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(jwtUserDetailsService);
        provider.setPasswordEncoder(encoder());
        
        return provider;
    }
    
    @Bean
    public PasswordEncoder encoder(){
        return new BCryptPasswordEncoder(12);
    }
}
注意:您可以使用
DaoAuthenticationProvider
在以下位置添加
jwtuserdetails服务来省略它:

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

通过这样做,我只是返回我试图自动连线的字段。。。为什么它要工作?spring会为您实例化它们。当您尝试使用一个新关键字实例化组件时,会出现混淆,spring会混淆删除
@Bean
,除了
AuthenticationManager
PasswordEncoder
之外。如果我这样做,它会说类的字段没有Bean。但是,如果我尝试在另一个类中自动关联相同的字段,它不会抱怨。看起来该类无法找到Bean。请发布类的实现:
JWTTokenUtils
这不是编译问题,伙计,再看一看。编译与CDI没有任何关系。如果我这样做了,那么它表示类的字段没有bean。但是,如果我尝试在另一个类中自动关联相同的字段,它不会抱怨。看起来该类无法找到bean。你提出的解决方案首先是我的问题。这是一个在prod中非常有效的解决方案,你能重新表述你的问题吗?
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)
}