创建名称为 authenticationTokenFilterBean 的 bean 时出错:通过字段 tokenUtils 表达的不满足的依赖关系
Posted
技术标签:
【中文标题】创建名称为 authenticationTokenFilterBean 的 bean 时出错:通过字段 tokenUtils 表达的不满足的依赖关系【英文标题】:Error creating bean with name authenticationTokenFilterBean: Unsatisfied dependency expressed through field tokenUtils 【发布时间】:2019-05-28 06:21:20 【问题描述】:我想在我的项目中实现 Spring Security。但是无论我尝试什么,我都会遇到同样的错误。
我创建了必要的类(TokenUtils
、AuthenticationTokenFilter
、SpringConfiguration
)。它们在同一个包下,但我收到以下错误。
这是我的Stack Trace
的一部分,出现问题的地方
2018-12-31 23:58:10.616 INFO 9952 --- [main] j.LocalContainerEntityManagerFactoryBean:为持久性单元“默认”初始化 JPA EntityManagerFactory 2018-12-31 23:58:11.444 错误 9952 --- [main] o.s.b.web.embedded.tomcat.TomcatStarter:启动 Tomcat 上下文时出错。例外:org.springframework.beans.factory.UnsatisfiedDependencyException。消息:创建名称为“authenticationTokenFilterBean”的 bean 时出错:通过字段“tokenUtils”表示的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“com.sbvtransport.sbvtransport.security.TokenUtils”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:@org.springframework.beans.factory.annotation.Autowired(required=true) 2018-12-31 23:58:11.479 INFO 9952 --- [main] o.apache.catalina.core.StandardService:停止服务 [Tomcat] 2018-12-31 23:58:11.495 WARN 9952 --- [main] o.a.c.loader.WebappClassLoaderBase:Web 应用程序 [ROOT] 似乎已经启动了一个名为 [HikariPool-1 housekeeper] 的线程,但未能停止它。这很可能造成内存泄漏。线程的堆栈跟踪: java.base@11.0.1/jdk.internal.misc.Unsafe.park(本机方法) java.base@11.0.1/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:234) java.base@11.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2123) java.base@11.0.1/java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1182) java.base@11.0.1/java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:899) java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1054) java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1114) java.base@11.0.1/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) java.base@11.0.1/java.lang.Thread.run(Thread.java:834) 警告:发生了非法反射访问操作 警告:org.apache.catalina.loader.WebappClassLoaderBase 的非法反射访问(文件:/C:/Users/Danijela/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/9.0.12/tomcat -embed-core-9.0.12.jar) 到字段 java.io.ObjectStreamClass$Caches.localDescs 警告:请考虑将此报告给 org.apache.catalina.loader.WebappClassLoaderBase 的维护者 警告:使用 --illegal-access=warn 启用对进一步非法反射访问操作的警告 警告:所有非法访问操作将在未来版本中被拒绝 2018-12-31 23:58:11.502 WARN 9952 --- [main] ConfigServletWebServerApplicationContext:上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.context.ApplicationContextException:无法启动 Web 服务器;嵌套异常是 org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat 2018-12-31 23:58:11.502 INFO 9952 --- [main] j.LocalContainerEntityManagerFactoryBean:为持久性单元“默认”关闭 JPA EntityManagerFactory 2018-12-31 23:58:11.502 INFO 9952 --- [main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - 已启动关闭... 2018-12-31 23:58:11.517 INFO 9952 --- [main] com.zaxxer.hikari.HikariDataSource:HikariPool-1 - 关闭完成。 2018-12-31 23:58:11.533 INFO 9952 --- [主要] ConditionEvaluationReportLoggingListener:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-12-31 23:58:11.845 ERROR 9952 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field tokenUtils in com.sbvtransport.sbvtransport.security.AuthenticationTokenFilter required a bean of type 'com.sbvtransport.sbvtransport.security.TokenUtils' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.sbvtransport.sbvtransport.security.TokenUtils' in your configuration.
package com.sbvtransport.sbvtransport.security;
这些是我的安全类:
AuthenticationTokenFilter
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter
@Autowired
TokenUtils tokenUtils;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
HttpServletRequest httpRequest = (HttpServletRequest) request;
String authToken = httpRequest.getHeader("Authorization");
String username = tokenUtils.getUsernameFromToken(authToken);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null)
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (tokenUtils.validateToken(authToken, userDetails))
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
TokenUtils
package com.sbvtransport.sbvtransport.security;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class TokenUtils
@Value("SuperSecreat")
private String secret;
@Value("86400") // 24 hours(in seconds)
private Long expiration;
public String getUsernameFromToken(String token)
String username;
try
Claims claims = this.getClaimsFromToken(token);
username = claims.getSubject();
catch (Exception e)
username = null;
return username;
private Claims getClaimsFromToken(String token)
Claims claims;
try
claims = Jwts.parser().setSigningKey(this.secret).parseClaimsJws(token).getBody();
catch (Exception e)
claims = null;
return claims;
public Date getExpirationDateFromToken(String token)
Date expirationDate;
try
final Claims claims = this.getClaimsFromToken(token);
expirationDate = claims.getExpiration();
catch (Exception e)
expirationDate = null;
return expirationDate;
private boolean isTokenExpired(String token)
final Date expirationDate = this.getExpirationDateFromToken(token);
return expirationDate.before(new Date(System.currentTimeMillis()));
public boolean validateToken(String token, UserDetails userDetails)
final String username = getUsernameFromToken(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
public String generateToken(UserDetails userDetails)
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("sub", userDetails.getUsername());
claims.put("created", new Date(System.currentTimeMillis()));
return Jwts.builder().setClaims(claims).setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
.signWith(SignatureAlgorithm.HS512, secret).compact();
安全配置
package com.sbvtransport.sbvtransport.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@SpringBootApplication
@Configuration
@EnableWebSecurity
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception
authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
@Bean
public PasswordEncoder passwordEncoder()
return new BCryptPasswordEncoder();
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Bean
public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception
AuthenticationTokenFilter authenticationTokenFilter = new AuthenticationTokenFilter();
authenticationTokenFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationTokenFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
httpSecurity.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("").permitAll();
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
在 AuthenticationTokenFilter 中自动装配 TokenUtils 似乎有问题,但我也可能错了。
我希望我的问题足够清楚,如果我可以做任何改进,请提出建议。
【问题讨论】:
【参考方案1】:错误:错误信息明确指出TokenUtils
bean is not found
'com.sbvtransport.sbvtransport.security.TokenUtils' 找不到。
您在TokenUtils
上缺少@Component
,使用@Component
声明类会使组件扫描以在应用程序上下文中创建此类的单例bean
@Component
public class TokenUtils
和@Configuration
AuthenticationTokenFilter
@Configuration
public class AuthenticationTokenFilter extends UsernamePasswordAuthenticationFilter
@SpringBootApplication 在声明的包中启用组件扫描
@EnableAutoConfiguration:启用 Spring Boot 的自动配置机制
@ComponentScan:对应用所在的包启用@Component扫描(见最佳实践)
@Configuration:允许在上下文中注册额外的bean或导入额外的配置类
@SpringBootApplication 注解等效于使用@Configuration、@EnableAutoConfiguration 和@ComponentScan 及其默认属性,
【讨论】:
非常感谢,我不敢相信我错过了。我刚刚开始使用 Spring。以上是关于创建名称为 authenticationTokenFilterBean 的 bean 时出错:通过字段 tokenUtils 表达的不满足的依赖关系的主要内容,如果未能解决你的问题,请参考以下文章
使用 Apache Shiro 从 session/authenticationtoken/cache 中检索用户信息
Realm [*] was unable to find account data for the submitted AuthenticationToken
为啥我们得到 BeanCreationException:创建名称为“springSecurityFilterChain”的 bean 时出错? [复制]