问题描述
我在 Spring Boot 中构建了一个 REST API,它在从 main 运行并用 Postman 测试时完美运行。现在我将使用 JUnit 5 为控制器实现自动化测试,对于这些测试,我不想模拟依赖项,我想使用实际的存储库,与真正的测试 (h2) 数据库等交互,所以我尝试使用 @SpringBoottest 注释加载完整的应用程序上下文。这是第一个测试文件。
@SpringBoottest
@AutoConfiguremockmvc
class AuthControllerTest {
@Autowired
private mockmvc mockmvc;
@Test
void registerUser() {
}
@Test
void authenticateUser() {
}
}
当运行测试只是为了检查一切配置是否正常时,我得到以下堆栈跟踪...
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcesstestInstance(SpringExtension.java:138)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:350)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:355)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$7(ClassBasedTestDescriptor.java:350)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:349)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcesstestInstance$4(ClassBasedTestDescriptor.java:270)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcesstestInstance(ClassBasedTestDescriptor.java:269)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:259)
at java.base/java.util.Optional.orElseGet(Optional.java:364)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:258)
at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:101)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:100)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:65)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionorchestrator.execute(EngineExecutionorchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionorchestrator.execute(EngineExecutionorchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionorchestrator.lambda$execute$0(EngineExecutionorchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionorchestrator.withInterceptedStreams(EngineExecutionorchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionorchestrator.execute(EngineExecutionorchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at com.intellij.junit5.junit5IdeaTestRunner.startRunnerWithArgs(junit5IdeaTestRunner.java:71)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:221)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'authController' defined in file [C:\Users\mspen\coding\projects\chitter-java\target\classes\com\malachispencer\chitterjava\controllers\AuthController.class]: Unsatisfied dependency expressed through constructor parameter 2; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'jwtFilter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtFilter' defined in file [C:\Users\mspen\coding\projects\chitter-java\target\classes\com\malachispencer\chitterjava\security\jwt\JwtFilter.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtProvider': Injection of autowired dependencies Failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CHITTER_JAVA_JWT_KEY' in value "${CHITTER_JAVA_JWT_KEY}"
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.autowireConstructor(AbstractAutowireCapablebeanfactory.java:1354)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBeanInstance(AbstractAutowireCapablebeanfactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524)
at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333)
at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.preInstantiateSingletons(DefaultListablebeanfactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishbeanfactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 67 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfig': Unsatisfied dependency expressed through field 'jwtFilter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtFilter' defined in file [C:\Users\mspen\coding\projects\chitter-java\target\classes\com\malachispencer\chitterjava\security\jwt\JwtFilter.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtProvider': Injection of autowired dependencies Failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CHITTER_JAVA_JWT_KEY' in value "${CHITTER_JAVA_JWT_KEY}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessproperties(AutowiredAnnotationBeanPostProcessor.java:399)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.populateBean(AbstractAutowireCapablebeanfactory.java:1413)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:601)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524)
at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333)
at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.instantiateUsingFactoryMethod(AbstractAutowireCapablebeanfactory.java:1334)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBeanInstance(AbstractAutowireCapablebeanfactory.java:1177)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524)
at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333)
at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1380)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 86 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtFilter' defined in file [C:\Users\mspen\coding\projects\chitter-java\target\classes\com\malachispencer\chitterjava\security\jwt\JwtFilter.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtProvider': Injection of autowired dependencies Failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CHITTER_JAVA_JWT_KEY' in value "${CHITTER_JAVA_JWT_KEY}"
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.autowireConstructor(AbstractAutowireCapablebeanfactory.java:1354)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBeanInstance(AbstractAutowireCapablebeanfactory.java:1204)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:564)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524)
at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333)
at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1380)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
... 110 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jwtProvider': Injection of autowired dependencies Failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'CHITTER_JAVA_JWT_KEY' in value "${CHITTER_JAVA_JWT_KEY}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessproperties(AutowiredAnnotationBeanPostProcessor.java:405)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.populateBean(AbstractAutowireCapablebeanfactory.java:1413)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.doCreateBean(AbstractAutowireCapablebeanfactory.java:601)
at org.springframework.beans.factory.support.AbstractAutowireCapablebeanfactory.createBean(AbstractAutowireCapablebeanfactory.java:524)
at org.springframework.beans.factory.support.Abstractbeanfactory.lambda$doGetBean$0(Abstractbeanfactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.Abstractbeanfactory.doGetBean(Abstractbeanfactory.java:333)
at org.springframework.beans.factory.support.Abstractbeanfactory.getBean(Abstractbeanfactory.java:208)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1380)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791)
... 123 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'CHITTER_JAVA_JWT_KEY' in value "${CHITTER_JAVA_JWT_KEY}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolverequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processproperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.Abstractbeanfactory.resolveEmbeddedValue(Abstractbeanfactory.java:936)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.doResolveDependency(DefaultListablebeanfactory.java:1321)
at org.springframework.beans.factory.support.DefaultListablebeanfactory.resolveDependency(DefaultListablebeanfactory.java:1300)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessproperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 135 more
如您所见,有许多“org.springframework.beans.factory.UnsatisfiedDependencyException”异常。这些异常涉及的类是:
src/main/java/com/malachispencer/chitterjava/security/SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtFilter jwtFilter;
@Autowired
private AuthEntryPointImpl unauthorizedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/*").permitAll()
.antMatchers(HttpMethod.GET,"/posts/**").permitAll()
.antMatchers(HttpMethod.POST,"/posts/**").hasRole("USER")
.antMatchers(HttpMethod.PATCH,"/posts/**").hasRole("USER")
.antMatchers(HttpMethod.DELETE,"/posts/**").hasRole("USER");
http.addFilterBefore(jwtFilter,UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
src/main/java/com/malachispencer/chitterjava/security/jwt/JwtFilter.java
@Component
@Log
public class JwtFilter extends GenericFilterBean {
private JwtProvider jwtProvider;
private UserDetailsServiceImpl userDetailsService;
public JwtFilter(
JwtProvider jwtProvider,UserDetailsServiceImpl userDetailsService
) {
this.jwtProvider = jwtProvider;
this.userDetailsService = userDetailsService;
}
@Override
public void doFilter(
ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain
) throws IOException,servletexception {
try {
String jwtToken = getTokenFromrequest(
(HttpServletRequest) servletRequest
);
if (jwtToken != null && jwtProvider.validatetoken(jwtToken)) {
String username = jwtProvider.getUsernameFromToken(jwtToken);
UserDetails userDetails = userDetailsService
.loadUserByUsername(username);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
userDetails,null,userDetails.getAuthorities()
);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} catch (Exception e) {
log.severe("CANNOT SET USER AUTHENTICATION\n" + e.getMessage());
}
filterChain.doFilter(servletRequest,servletResponse);
}
private String getTokenFromrequest(HttpServletRequest request) {
String bearer = request.getHeader("Authorization");
if (StringUtils.hasText(bearer) && bearer.startsWith("Bearer ")) {
return bearer.substring(7);
}
return null;
}
}
src/main/java/com/malachispencer/chitterjava/security/jwt/JwtProvider.java
@Log
@Component
public class JwtProvider {
@Value("${CHITTER_JAVA_JWT_KEY}")
private String jwtSecret;
@Value("${CHITTER_JAVA_JWT_EXPIRY}")
private Integer jwtExpirationMs;
public String generatetoken(Authentication auth) {
UserDetailsImpl userDetails = (UserDetailsImpl) auth.getPrincipal();
String username = userDetails.getUsername();
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(new Date().getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512,jwtSecret)
.compact();
}
public boolean validatetoken(String token) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
return true;
} catch (SignatureException e) {
log.severe("INVALID JWT SIGNATURE\n" + e.getMessage());
} catch (MalformedJwtException e) {
log.severe("INVALID JWT TOKEN\n" + e.getMessage());
} catch (ExpiredJwtException e) {
log.severe("JWT TOKEN IS EXPIRED\n" + e.getMessage());
} catch (UnsupportedJwtException e) {
log.severe("JWT TOKEN IS UNSUPPORTED\n" + e.getMessage());
} catch (IllegalArgumentException e) {
log.severe("JWT CLAims STRING IS EMPTY\n" + e.getMessage());
}
return false;
}
public String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(jwtSecret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
src/main/java/com/malachispencer/chitterjava/controllers/AuthController.java
@RestController
@RequestMapping("/auth")
public class AuthController {
private UserRepository userRepository;
private RoleRepository roleRepository;
private PasswordEncoder passwordEncoder;
private AuthenticationManager authenticationManager;
private JwtProvider jwtProvider;
public AuthController(
UserRepository userRepository,RoleRepository roleRepository,PasswordEncoder passwordEncoder,AuthenticationManager authenticationManager,JwtProvider jwtProvider
) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager;
this.jwtProvider = jwtProvider;
}
// rest of the controller
我已经尝试了记录类似问题的 Stack Overflow 帖子中提到的所有建议解决方案。到目前为止,一切都没有奏效。我正在尝试深入了解 Spring 以深入了解应用程序上下文和 Bean。非常感谢建议和解决方案。
解决方法
我猜问题是关于application.properties
。 Spring 尝试在测试资源文件夹中找到它,但失败了。尝试添加一个
如果您将异常链跟踪到底,您将看到根本原因:
无法解析值“${CHITTER_JAVA_JWT_KEY}”中的占位符“CHITTER_JAVA_JWT_KEY”
所以由于某种原因没有找到 CHITTER_JAVA_JWT_KEY。您将不得不检查您的配置,这是如何发生的。最常见的问题是:
- 与运行测试时相比,您在运行应用程序时是否激活了任何配置文件?
- 您的测试在包层次结构中与主
@SpringBootApplication
类处于相同级别还是更低级别? IE。我假设这将是com.malachispencer.chitterjava
,因此测试需要在该包或其子包中。 - 如何启动主应用程序?您是否以测试不会采用的方式传入
CHITTER_JAVA_JWT_KEY
属性?例如。在命令行上使用-DCHITTER_JAVA_JWT_KEY
或作为 env 变量。特别是如果您从 IDE 运行它,您是否有主应用程序的运行配置与测试运行配置在这方面有所不同?