我正在尝试实现 Web 安全配置,而不实现已弃用的 WebSecurityConfigurerAdapter。但是当我尝试验证 User AuthenticationManager 时,出现 stackOverFlow 错误。这是网络安全配置类。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**",
"/swagger-ui.html", "/webjars/**");
}
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
这是我尝试访问authenticationManager的方法。
@Service
public class AuthService {
@Autowired
private AuthenticationManager authenticationManager;
public Optional<Authentication> authenticateUser(LoginRequest loginRequest) {
return Optional.ofNullable(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getEmail(),
loginRequest.getPassword())));
}
}
这是错误本身。
java.lang.StackOverflowError: null
at java.base/java.lang.Exception.<init>(Exception.java:103) ~[na:na]
at java.base/java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:90) ~[na:na]
at java.base/java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:67) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor69.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:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.22.jar:5.3.22]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.22.jar:5.3.22]
at jdk.proxy2/jdk.proxy2.$Proxy151.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor69.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:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.22.jar:5.3.22]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.22.jar:5.3.22]
at jdk.proxy2/jdk.proxy2.$Proxy151.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor69.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:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.22.jar:5.3.22]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.22.jar:5.3.22]
at jdk.proxy2/jdk.proxy2.$Proxy151.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor69.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:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.22.jar:5.3.22]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) ~[spring-aop-5.3.22.jar:5.3.22]
at jdk.proxy2/jdk.proxy2.$Proxy151.authenticate(Unknown Source) ~[na:na]
at jdk.internal.reflect.GeneratedMethodAccessor69.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:568) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.22.jar:5.3.22]
我也遇到了这个问题,但我使用下面的代码
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
看到这个问题:
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:211)
at jdk.proxy2/jdk.proxy2.$Proxy72.authenticate(Unknown Source)
at jdk.internal.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
其实,我看到其他人的回答并尝试了两次以上,发现下面的方法是可行的:
@Configuration
@EnableWebSecurity
public class SecurityConfig{
//rewrite loadByUsername in UserDetailsServiceImpl and I inject it in Spring Container
@Autowired
UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
return authenticationManagerBuilder.build();
}
}
效果非常好。
我有一个类似的问题,我需要一个 AuthenticationManager 来创建 AuthenticationFilter。我最终得到了这个解决方案:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// ...
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver = r -> authenticationManagerBuilder.getOrBuild();
AuthenticationFilter filter = new AuthenticationFilter(authenticationManagerResolver, ...);
// ...
return http.build();
}