com.api.WebSecurityConfig 中的字段 myUserDetailsService 需要一个 bean,但找到了 2 个
Posted
技术标签:
【中文标题】com.api.WebSecurityConfig 中的字段 myUserDetailsService 需要一个 bean,但找到了 2 个【英文标题】:Field myUserDetailsService in com.api.WebSecurityConfig required a single bean, but 2 were found 【发布时间】:2021-04-23 00:50:32 【问题描述】:完全错误: :
user1:在文件中定义 [/tools/tomcat/instances/webapps/api/WEB-INF/classes/com/api/jwt/users/test1.class] user2:在文件中定义 [/tools/tomcat/instances/webapps/api/WEB-INF/classes/com/api/jwt/users/test2.class]我有以下课程:
Test1.java
@Service
@Component("user1")
public class Test1 implements UserDetailsService
@Value("$test1.username")
private String test1Username;
@Value("$test1.password")
private String test1Password;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
if (username != null && username.equals(test1Username))
return new User(username, test1Password, new ArrayList<>());
else
throw new UsernameNotFoundException("Username not found: " + username);
Test2.java
@Service
@Component("user2")
public class Test2 implements UserDetailsService
@Value("$test2.username")
private String test2Username;
@Value("$test2.password")
private String test2Password;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
if (username != null && username.equals(test2Username))
return new User(username, test2Password, new ArrayList<>());
else
throw new UsernameNotFoundException("Username not found: " + username);
SpringMainApplication.java
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService myUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(myUserDetailsService);
@Bean
public PasswordEncoder passwordEncoder()
return NoOpPasswordEncoder.getInstance();
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/**/access-token").permitAll().
anyRequest().authenticated().and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
JwtRequestFilter.java
@Component
public class JwtRequestFilter extends OncePerRequestFilter
@Autowired
@Qualifier(value = "user1")
private Test1 test1;
@Autowired
@Qualifier(value = "user2")
private Test2 test2;
@Override
protected void doFilterInternal() throws ServletException, IOException
// SOME CODE
我以为通过使用@Component
和@Qualifier
,我可以设置两个用户详细信息类,但似乎并非如此。
有什么我遗漏的或者在这个设计中是不可能的吗?
如果我创建另一个名为 MyUserDetailsService.java
的类,则编译工作正常,并且在各自的端点中访问正确的类。我只是不明白为什么MyUserDetailsService
必须存在并且我不能使用Test1
和Test2
作为用户类。
编辑:
Test1.java
@Service
@Component("myUserDetailsService")
public class Test1 implements UserDetailsService
@Value("$test1.username")
private String test1Username;
@Value("$test1.password")
private String test1Password;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
if (username != null && username.equals(test1Username))
return new User(username, test1Password, new ArrayList<>());
else
throw new UsernameNotFoundException("Username not found: " + username);
Test2.java
@Service
@Component("myUserDetailsService")
public class Test2 implements UserDetailsService
@Value("$test2.username")
private String test2Username;
@Value("$test2.password")
private String test2Password;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
if (username != null && username.equals(test2Username))
return new User(username, test2Password, new ArrayList<>());
else
throw new UsernameNotFoundException("Username not found: " + username);
SpringMainApplication.java
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
@Qualifier(value = "myUserDetailsService")
private UserDetailsService myUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(myUserDetailsService);
@Bean
public PasswordEncoder passwordEncoder()
return NoOpPasswordEncoder.getInstance();
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/**/access-token").permitAll().
anyRequest().authenticated().and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
JwtRequestFilter.java
@Component
public class JwtRequestFilter extends OncePerRequestFilter
@Autowired
private Test1 test1;
@Autowired
private Test2 test2;
@Override
protected void doFilterInternal() throws ServletException, IOException
// SOME CODE
这给了我以下错误:
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.api.SpringMainApplication];
nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'myUserDetailsService' for bean class [com.api.jwt.users.Test2DetailsService] conflicts with existing, non-compatible bean definition of same name and class [com.api.jwt.users.Test1DetailsService]
【问题讨论】:
【参考方案1】:这些声明不需要限定符。 Spring 可以按类型注入它们,因为每种类型(Test1 和 Test2)都有一个匹配的 bean。
@Autowired
@Qualifier(value = "user1")
private Test1 test1;
@Autowired
@Qualifier(value = "user2")
private Test2 test2;
但是,您确实需要此声明的限定符,因为您有两个 UserDetailsService
实现,并且 spring 不知道要注入哪一个,从而导致错误。
@Autowired
private UserDetailsService myUserDetailsService;
编辑
在您更新的示例中,您定义了两个具有相同 bean id 的 bean
@Component("myUserDetailsService")
public class Test1 implements UserDetailsService
@Component("myUserDetailsService")
public class Test2 implements UserDetailsService
这会导致您看到的新错误(查看Spring documentation 可能会有所帮助):
注解指定的 bean 名称 'myUserDetailsService' 用于 bean 类 [com.api.jwt.users.Test2DetailsService] 与现有冲突, 相同名称和类的不兼容 bean 定义 [com.api.jwt.users.Test1DetailsService]
在您的示例中,拥有两个 UserDetailsService
实现并没有真正意义。您可以通过将它们组合成一个类来重构。
【讨论】:
我编辑了我的问题。你介意再看一下吗? 我认为我遇到的问题是我无法同时加载 user1 和 user2。它是一个或另一个,但我需要加载它们,因为它们有自己特定的令牌秘密和端点。 基本上我的问题是是否有办法在没有MyUserDetailsService
类的情况下使用Test1
和Test2
。现在我有所有 3 个类并且它可以工作,但如果我可以删除 MyUserDetailsService
将是理想的,所以我不会有双重代码。以上是关于com.api.WebSecurityConfig 中的字段 myUserDetailsService 需要一个 bean,但找到了 2 个的主要内容,如果未能解决你的问题,请参考以下文章