【发布时间】:2022-11-03 18:54:37
【问题描述】:
我在使用authenticationManger.authenticate() 时收到StackOverflowError。我看到这里已经回答了问题:Why AuthenticationManager is throwing StackOverflowError?,但我没有扩展已弃用的WebSecurityConfigurerAdapter,所以我的配置如下所示:
@Configuration
@EnableWebSecurity
public class SecurityConfig{
@Bean
public UserDetailsService userDetailsService() {
return new CustomUserDetailsService();
}
@Bean
@Order(1)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.httpBasic().disable().csrf().disable().sessionManagement()
.and().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated().and().csrf().disable();
http
.logout()
.invalidateHttpSession(true)
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK));
return http.build();
}
@Bean
@Order(0)
public SecurityFilterChain resources(HttpSecurity http) throws Exception {
http.requestMatchers((matchers) -> matchers.antMatchers("*.bundle.*"))
.authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll())
.requestCache().disable()
.securityContext().disable()
.sessionManagement().disable();
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public PasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
我仍然得到
2022-07-18 17:26:52.277 ERROR 12368 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.21.jar:5.3.21]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.21.jar:5.3.21]
at com.sun.proxy.$Proxy111.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor60.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.21.jar:5.3.21]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.21.jar:5.3.21]
at com.sun.proxy.$Proxy111.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor60.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.21.jar:5.3.21]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.21.jar:5.3.21]
at com.sun.proxy.$Proxy111.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor60.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
*continues till stack overflow*
我在这里借用的AuthenticationManager bean 的当前版本(在评论部分):spring.io docs
我在控制器中使用AuthenticationManager 手动验证用户身份:
@CrossOrigin
@RestController
public class UserController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
CustomUserService userService;
@Autowired
JwtTokenProvider jwtTokenProvider;
@PostMapping("/login")
public ResponseEntity<Map<Object, Object>> login(@RequestBody CustomUserLoginDto userDto) {
try {
String email = userDto.getEmail();
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, userDto.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = jwtTokenProvider.createToken(email);
Map<Object, Object> model = new HashMap<>();
model.put("username", email);
model.put("token", token);
return ResponseEntity.ok(model);
} catch (AuthenticationException e) {
throw new BadCredentialsException("Invalid email/password supplied");
}
}
@PostMapping("/register")
public CustomUser register(@RequestBody CustomUserCreateDto userDto) {
return userService.saveUser(userDto);
}
}
我该如何解决这个问题?
【问题讨论】:
-
我依稀记得从 WebSecurityConfigurerAdapter 转换时遇到了类似的情况。如果删除 AuthenticationManager bean 会发生什么?
-
@LeeGreiner,整个安全系统都没有,但我想在控制器中使用这个 bean,所以我必须定义它。如果有其他方法来定义它,我也想知道,谢谢
-
为什么需要控制器中的
AuthenticationManager?您能否描述请求并调试FilterChainProxy并找到导致堆栈溢出的过滤器? -
在幕后是一个 AuthenticationManagerBuilder。我的猜测是 AuthenticationManager bean 在您的控制器中可用,但我不得不问您为什么在控制器中需要它。
-
@LeeGreiner 添加了相关信息,请参阅问题
标签: java spring-boot spring-security jwt