我正在运行一个SpringBoot应用程序,其根类注释为@SpringBootApplication
,@EnableAutoConfiguration
。
我已经创建了一个UserRepositoryInterface
界面,扩展我的用户 JPA 对象的CrudRepository
界面。这个界面没有实现,也没有必要。此应用程序中的任何内容都没有任何配置文件。除了JPA DB连接,但是有效。
public interface UsersRepositoryInterface extends CrudRepository<User, Long> {
// Query to search for users via email
List<User> findByEmail(@Param("email") String email);
}
我已成功将其自动装入某些REST端点。当我尝试将其自动装入我的安全类时,问题出现了。我正在尝试使用JWT进行身份验证,但它确实有效。现在我想在登录过程中调用数据库,我遇到了问题。以下是课程:
首先是WebSecurityConfiguererAdapter
类,我在其中添加了过滤器的路径。请注意&#34; new JWTLoginFilter
&#34;的行,这是我尝试自动装配的类:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsServ;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
//Allow options pre-flight request
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
// Allow POST request to /login
.antMatchers(HttpMethod.POST, "/login").permitAll()
// Others must be authenticated
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Change logging in from username+password to email+password
auth.userDetailsService(userDetailsServ);
}
}
JWTLoginFilter
课程。我省略了一些不相关的代码:
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
@Autowired
private UsersRepositoryInterface userRepo;
public JWTLoginFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(
HttpServletRequest req, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
//Check if userRepo is injected
if(userRepo == null) {
System.out.println("Null");
}
AccountCredentials creds = new ObjectMapper()
.readValue(req.getInputStream(), AccountCredentials.class);
return getAuthenticationManager().authenticate(
new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
Collections.emptyList()
)
);
}
}
println
中的JWTLoginFilter
在被调用时将始终返回 Null 。
我错过了什么吗?
解决方法:
立即行动。
使用
注释JWTLoginFilter@Component("someName")
使用
将其注入WebSecurityConfig@Resource(name="someName")
private JWTLoginFilter myFilter;
在JWTLoginFilter构造函数中对URL进行硬编码,但我仍然需要将AuthenticationManager从WebSecurityConfig自动装配到JWTLoginFilter中。
首先必须使AuthenticationManager成为Bean。在这里使用答案:How To Inject AuthenticationManager using Java Configuration in a Custom Filter
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
然后在这里注入答案:Spring Security authenticationmanager must be specified - for custom filter
@Override
@Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
删除
setAuthenticationManager(authManager);
答案 0 :(得分:2)
那么,你期待什么?您正在通过JWTLoginFilter
关键字创建new
。 Spring根本没有做任何接线。您应该将此过滤条件设为@Bean
或@Component
或其他任何内容,使其成为spring bean
并以某种方式将其注入WebSecurityConfig
。
答案 1 :(得分:1)
我希望你的问题已经解决了。但我正在添加一个示例代码段,供那些面临同样问题的人参考。
当我们的过滤器包含Autowired依赖项时,使用new()在spring配置中实例化我们的过滤器不会自动装配其依赖项,因为这不是字符串托管bean。因此,我们需要在spring应用程序配置类中自动装配我们的过滤器,而后者又自动装配其内部依赖项。
PFB示例代码供参考。
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
@Autowired
private MyFilter myFilter;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MyApplication.class);
}
@Bean
public FilterRegistrationBean myFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(myFilter);
registration.addUrlPatterns("*");
return registration;
}
}
过滤器:
@Component
public class MyFilter extends BaseFilter {
@Autowired
private EmployeeRepository employeeRepository;
//your code goes here
if(employeeRepository != null) {
System.out.println("employeeRepository is not null");
}
}