kag*_*ire 7 java spring-security jwt spring-boot
StackOverflowError我在使用时得到authenticationManger.authenticate()。我看到这里已经回答了问题:Why AuthenticationManager is throwing StackOverflowError? ,但我没有扩展 deprecated 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();
}
}
Run Code Online (Sandbox Code Playgroud)
我仍然得到
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*
Run Code Online (Sandbox Code Playgroud)
我在这里借用的 bean的当前版本AuthenticationManager(在评论部分):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);
}
}
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?
小智 1
最好用扩展的自定义过滤器替换您的登录方法AbstractAuthenticationProcessingFilter
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
protected AuthenticationFilter() {
super("/login");
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equalsIgnoreCase(HttpMethod.POST.name())) {
return null;
}
// extract login and password
return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(login, password));
}
}
Run Code Online (Sandbox Code Playgroud)
要访问,AuthenticationManager您应该使用自定义 DSL(访问本地 AuthenticationManager)
public class CustomDsl extends AbstractHttpConfigurer<CustomDsl, HttpSecurity> {
@Override
public void configure(HttpSecurity http) throws Exception {
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
http.addFilterAfter(authenticationFilter(authenticationManager), ConcurrentSessionFilter.class);
}
public AuthenticationFilter authenticationFilter(AuthenticationManager authenticationManager) {
final AuthenticationFilter authenticationFilter = new AuthenticationFilter();
authenticationFilter.setAuthenticationManager(authenticationManager);
authenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
authenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
return authenticationFilter;
}
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new CustomAuthenticationSuccessHandler();
}
public AuthenticationFailureHandler authenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
}
Run Code Online (Sandbox Code Playgroud)
然后应用它
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
http.apply(customDsl());
return http.build();
}
Run Code Online (Sandbox Code Playgroud)
并从您的配置中删除它
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1571 次 |
| 最近记录: |