我有一个通过JWT进行身份验证的Spring Boot REST API。我的问题是,我已将Spring Security配置为允许无限制地访问用于身份验证的路径/auth/token,但是当它不应该被访问时,它仍然会击中我的安全过滤器。不知道我在哪里错了,任何建议都非常适合
/auth/token
安全配置
public class JwtWebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtAuthenticationEntryPoint unauthorizedHandler; @Autowired private UserDetailsService userDetailsService; @Autowired public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { authenticationManagerBuilder .userDetailsService(this.userDetailsService) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public JwtAuthenticationFilter authenticationTokenFilter() throws Exception { return new JwtAuthenticationFilter(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity .authorizeRequests() .antMatchers("/auth/token").permitAll() // do not authenticate .anyRequest().authenticated() // TODO: configure .cors() .and() // TODO enable and configure .csrf().disable() // Unauthorized request handler .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() // Keep application security stateless .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // JWT security filter httpSecurity.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); // Disable page caching to prevent cached REST responses httpSecurity.headers().cacheControl(); } @Override public void configure(WebSecurity webSecurity) throws Exception { webSecurity.ignoring().antMatchers(HttpMethod.POST, "/auth/token"); } }
过滤器
public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { // this runs } }
控制器
@RestController public class AuthenticationController { // Authenticate user @RequestMapping(value = "/auth/token", method = RequestMethod.POST) public ResponseEntity<?> createAuthenticationToken(HttpServletResponse response, @RequestBody JwtAuthenticationRequest authenticationRequest, Device device) throws AuthenticationException { // never gets to run } }
感谢@dur询问我是否正在使用Spring Boot,这使我找到了解决方案。
这使我开始考虑Spring Boot如何自动为我们自动创建bean,最终成为这里的罪魁祸首。事实证明,我的JwtAuthenticationFilter类是由Spring Boot自动放入过滤器链中的,但是当我在安全配置中显式声明它时,它也被包含在安全过滤器链中。因此,尽管我正确地排除/auth/token了ignoring()安全性配置中的方法,但这还不足以阻止过滤器在Spring Boot本身的上下文中发生。解决方案是配置一个显式阻止Spring Boot添加它的bean。
JwtAuthenticationFilter
ignoring()
@Bean public RegistrationBean jwtAuthFilterRegister(JwtAuthenticationFilter filter) { FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter); registrationBean.setEnabled(false); return registrationBean; }