【发布时间】:2021-06-20 13:38:39
【问题描述】:
当我尝试运行测试用例时,我一直在运行这个问题。无法弄清楚发生了什么。请问有什么帮助吗?谢谢。
Message:
N/A
Stack trace:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'webSecurityConfig': Unsatisfied dependency expressed through field 'jwtTokenProvider'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.utopia.auth.jwk.JwtTokenProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.utopia.auth.jwk.JwtTokenProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
... 89 more
enter code here
这是我的配置文件,这里发生的错误似乎基于堆栈跟踪。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenProvider jwtTokenProvider;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.logout().permitAll()
.logoutRequestMatcher(new AntPathRequestMatcher("/api/user/logout", "POST"))
.and()
.formLogin().loginPage("/auth/login").and()
.httpBasic().and()
.csrf().disable();
//jwt filter
http.addFilter(new JWTAuthorizationFilter(authenticationManager(),jwtTokenProvider));
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
//Cross origin resource sharing.
@Bean
public WebMvcConfigurer corsConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
}
};
}
}
以及实际的 JWTProvider 文件
@Component
public class JwtTokenProvider {
@Value("${app.jwt.secret}")
private String jwtSecret;
@Value("${app.jwt.token.prefix}")
private String jwtTokenPrefix;
@Value("${app.jwt.header.string}")
private String jwtHeaderString;
@Value("${app.jwt.expiration-in-ms}")
private Long jwtExpirationInMs;
public String generateToken(Authentication auth) {
String authorities = auth.getAuthorities().stream().map(GrantedAuthority::getAuthority)
.collect(Collectors.joining());
return Jwts.builder().setSubject(auth.getName()).claim("roles", authorities)
.setExpiration(new Date(System.currentTimeMillis() + jwtExpirationInMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}
public Authentication getAuthentication(HttpServletRequest request) {
String token = resolveToken(request);
if (token == null) {
return null;
}
Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
String username = claims.getSubject();
final List<GrantedAuthority> authorities = Arrays.stream(claims.get("roles").toString().split(","))
.map(role -> role.startsWith("ROLE_") ? role : "ROLE_" + role).map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
return username != null ? new UsernamePasswordAuthenticationToken(username, null, authorities) : null;
}
public boolean validateToken(HttpServletRequest request) {
String token = resolveToken(request);
if (token == null) {
return false;
}
Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
if (claims.getExpiration().before(new Date())) {
return false;
}
return true;
}
private String resolveToken(HttpServletRequest req) {
// Bearer key...
String bearerToken = req.getHeader(jwtHeaderString);
if (bearerToken != null && bearerToken.startsWith(jwtTokenPrefix)) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
老实说,我不明白 Spring 到底在抱怨什么。过去4个小时一直在调试它,仍然没有。 (
【问题讨论】:
-
错误信息很清楚,Spring没有找到你的
JwtTokenProviderbean。 SO上有很多类似的问题。你已经尝试了什么?你检查@Component的包了吗,有一些这个名字的类。您是否检查过您的班级是否在组件扫描路径上?如果你使用 Spring Boot,你的类是在 Spring Boot 应用类的子包中吗?
标签: java spring junit spring-security mocking