问题
I have a Spring Boot REST API that is authenticating via JWT. My issue is that I have configured Spring Security to allow unrestricted access to the the path used to authenticate /auth/token, but it is still hitting my security filter when it shouldn't be. Not sure where I've got wrong here any advice is greatly appropriated
The security config
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");
}
}
the filter
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
// this runs
}
}
The controller
@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
}
}
回答1:
Thanks to @dur for asking if I was using Spring Boot, which led me to the solution.
This is made me start thinking about how Spring Boot likes to automagically create beans for us on the fly, which ended up being the culprit here. Turns out that my JwtAuthenticationFilter class was being automatically put into the filter chain by Spring Boot, but also being included in the security filter chain when I explicitly declared it in my security config. So although I was correct to exclude /auth/token in the ignoring() method in security config, that wasn't enough to stop the filter from happening in the context of Spring Boot itself. The solution was to configure a bean that explicitly prevents it from being added by Spring Boot
@Bean
public RegistrationBean jwtAuthFilterRegister(JwtAuthenticationFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
回答2:
Just a suggestion.
Is it possible, that you are hitting not authentication, but cors?
Authentication - HTTP status 401
CORS - HTTP status 403
if you enable cors and don't configure it, it doesn't permitt any cros-origin requests. From CorsConfiguration javadoc:
By default a newly created CorsConfiguration does not permit any cross-origin requests and must be configured explicitly to indicate what should be allowed.
来源:https://stackoverflow.com/questions/46716914/spring-security-filter-chain-not-ignoring-specified-path