【发布时间】:2017-09-03 20:11:24
【问题描述】:
我正在运行一个 SpringBoot 应用程序,其根类使用 @SpringBootApplication、@EnableAutoConfiguration 进行注释。
我创建了一个UserRepositoryInterface 接口,它扩展 CrudRepository 接口与我的用户JPA 对象。这个接口没有实现,也不需要一个。此应用程序中也没有任何配置文件。 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 类,我在其中添加了过滤器的路径。请注意带有“new JWTLoginFilter”的行,这是我尝试自动装配的类:
@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()
)
);
}
}
JWTLoginFilter 中的 println 在被调用时将始终返回 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);
在 JWTLoginFilter 的构造函数中
【问题讨论】:
-
能否请您添加您的项目结构?
标签: java spring spring-boot dependency-injection autowired