英文:
Spring bean dependencies in the application context form a cycle
问题
我一直在尝试为我的项目添加JWT授权。我已经尝试过添加@Lazy,但没有起作用。
我不知道如何更新我的应用程序以移除依赖循环。
控制台:
应用程序上下文中某些bean的依赖关系形成循环:
┌─────┐
| jwtAuthenticationFilter 定义在文件 [C:\Users\User\Desktop\PizzaCloud2\target\classes\pizzas\security\authentication\JwtAuthenticationFilter.class]
↑ ↓
| securityConfig 定义在文件 [C:\Users\User\Desktop\PizzaCloud2\target\classes\pizzas\security\SecurityConfig.class]
└─────┘
操作:
不鼓励依赖循环,并且默认情况下是被禁止的。请更新您的应用程序以删除bean之间的依赖循环。作为最后的手段,可以通过将 spring.main.allow-circular-references 设置为 true 来尝试自动打破循环。
JwtAuthenticationFilter类:
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter{
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String username;
if (authHeader == null || !authHeader.startsWith("Bearer")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
SecurityConfig类:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
@Bean
public UserDetailsService userDetailsService(UserRepository userRepo) {
return username -> {
User2 user = userRepo.findByUsername(username);
if (user != null) {
return user;
}
throw new UsernameNotFoundException(
"用户 '" + username + "' 未找到");
};
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.csrf()
.disable()
/*.authorizeRequests()*/
.authorizeHttpRequests()
.requestMatchers("/design", "/orders").hasRole("USER")
.anyRequest().permitAll()
/*.anyRequest().authenticated()*/
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutSuccessUrl("/")
// 让H2-Console不受保护;用于调试目的
/*.and()
.csrf()
.ignoringRequestMatchers("/h2-console/**")*/
// 允许从同一来源加载帧的页面;H2-Console所需
.and()
.headers()
.frameOptions()
.sameOrigin()
.and()
.build();
}
}
将spring.main.allow-circular-references设置为true也没有帮助。
英文:
I've been trying to add jwt authorisation to my project. I've already tried adding @Lazy, that doesn't work.
I don't know how can I update my app to remove the dependency cycle.
Console:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| jwtAuthenticationFilter defined in file [C:\Users\User\Desktop\PizzaCloud2\target\classes\pizzas\security\authentication\JwtAuthenticationFilter.class]
↑ ↓
| securityConfig defined in file [C:\Users\User\Desktop\PizzaCloud2\target\classes\pizzas\security\SecurityConfig.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
JwtAuthenticationFilter class:
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter{
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Äuthorization");
final String jwt;
final String username;
if (authHeader == null || !authHeader.startsWith("Bearer")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
username = jwtService.extractUsername(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails, userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
SecurityConfig class:
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenticationProvider;
@Bean
public UserDetailsService userDetailsService(UserRepository userRepo) {
return username -> {
User2 user = userRepo.findByUsername(username);
if (user != null) {
return user;
}
throw new UsernameNotFoundException(
"User '" + username + "' not found");
};
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.csrf()
.disable()
/*.authorizeRequests()*/
.authorizeHttpRequests()
.requestMatchers("/design", "/orders").hasRole("USER")
.anyRequest().permitAll()
/*.anyRequest().authenticated()*/
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.formLogin()
.loginPage("/login")
.and()
.logout()
.logoutSuccessUrl("/")
// Make H2-Console non-secured; for debug purposes
/*.and()
.csrf()
.ignoringRequestMatchers("/h2-console/**")*/
// Allow pages to be loaded in frames from the same origin; needed for H2-Console
.and()
.headers()
.frameOptions()
.sameOrigin()
.and()
.build();
}
}
Setting spring.main.allow-circular-references to true doesn't help.
答案1
得分: 0
根据错误提示:“依赖循环引用是不鼓励的,而且默认情况下是禁止的...”
-
JwtAuthenticationFilter 在 SecurityConfig 中引用了 UserDetailsService
-
SecurityConfig 引用了 JwtAuthenticationFilter
解决方案:您可以将 @Bean UserDetailsService 移动到另一个配置类中。
英文:
As the error indicating: "Relying upon circular references is discouraged and they are prohibited by default..."
-
JwtAuthenticationFilter refer UserDetailsService in SecurityConfig
-
SecurityConfig refer JwtAuthenticationFilter
Solution: You can move @Bean UserDetailsService to another configuration class
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论