问题描述
我正在尝试通过@Autowired注释将过滤器JWTLoginFilter传递给WebSecurityConfig WebSecurityConfigurerAdapter.当JWTLoginFilter尝试从WebSecurityConfig获取AuthenticationManager时出现问题.
I'm trying pass filter JWTLoginFilter to WebSecurityConfig WebSecurityConfigurerAdapter by @Autowired annotation. The problem arise when JWTLoginFilter try get AuthenticationManager from WebSecurityConfig.
启动服务器时,出现此错误:
When I start server, I get this error:
应用程序上下文形式中的某些bean的依赖性 一个周期:
The dependencies of some of the beans in the application context form a cycle:
文件中定义的JWTLoginFilter [C:\ Users \ user \ workspace \ backend \ target \ classes \ pl \ dn \ schoolsystem \ service \ jwt \ JWTLoginFilter.class]
JWTLoginFilter defined in file [C:\Users\user\workspace\backend\target\classes\pl\dn\schoolsystem\service\jwt\JWTLoginFilter.class]
webSecurityConfig(字段 pl.dn.schoolsystem.service.jwt.JWTLoginFilter pl.dn.schoolsystem.config.WebSecurityConfig.jwtLoginFilter)
webSecurityConfig (field pl.dn.schoolsystem.service.jwt.JWTLoginFilter pl.dn.schoolsystem.config.WebSecurityConfig.jwtLoginFilter)
我认为这种循环依赖注入.我对此卡住了,我不知道如何解决.
I think this circular dependency injection. I got stuck on this and i have no idea how to solve it.
WebSecurityConfig:
WebSecurityConfig:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Autowired
private UserSecurityService userSecurityService;
@Autowired
JWTLoginFilter jwtLoginFilter;
private static final String Salt = "salt"; // should be protected better
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12, new SecureRandom(Salt.getBytes()));
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().
authorizeRequests().antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
//UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(jwtLoginFilter,
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
}
}
JWTLoginFilter:
JWTLoginFilter:
@Component
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{
@Autowired
UserService userService;
@Autowired
public JWTLoginFilter(@Value("/login") String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException,
IOException, ServletException {
System.out.println("Jestem w JwtLogginFilter.attemptAuthentication -------------------------------------");
AccountCredentials creds = new ObjectMapper()
.readValue(req.getInputStream(), AccountCredentials.class);
User user = userService.findByUsername(creds.getUsername());
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
user.getAuthorities()
)
);
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
System.out.println("Jestem w JWTLogginFilter.successfulAuthentication -------------------------------------- ");
System.out.println("authResult.getName(): " + authResult.getName());
TokenAuthenticationService.addAuthentication(response, authResult.getName());
}
}
我正在使用Spring Boot 1.5.4.感谢您的建议
I'm using Spring Boot 1.5.4. Thanks for suggestions
推荐答案
您的WebSecurityConfig
明确请求将JWTLoginFilter
注入其中,而JWTLoginFilter
请求将AuthenticationManager
注入其构造函数中. AuthenticationManager
由WebSecurityConfig
提供,因此具有循环依赖项.
Your WebSecurityConfig
explicitly requests JWTLoginFilter
to be injected in it, and JWTLoginFilter
requests AuthenticationManager
to be injected in its constructor. AuthenticationManager
is supplied by WebSecurityConfig
, so you have a circular dependency.
从JWTLoginFilter
中删除@Component
批注,并将过滤器定义为WebSecurityConfig
中的Bean:
Remove @Component
annotation from JWTLoginFilter
and define the filter as a bean in WebSecurityConfig
:
@Bean
public JWTLoginFilter jwtLoginFilter() {
return new JWTLoginFilter("/login", authenticationManager());
}
您可能还需要在此方法中手动注入UserService
(例如,通过构造函数).
You will probably also need to inject UserService
manually in this method (for example, via constructor).
这篇关于无法通过@Autowired将AuthenticationManager传递到自定义过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!