I'm trying to learn spring security but stuck on filters. I know that oncePerRequestFilter works for each request and I'm planning to check JWT token in this filter. But if user is new and tries to reach /auth/login endpoint then somehow I need to say this filter to allow, then execute my method for /auth/login. But I couldn't find to way to run that method.
This is my OncePerRequestFilter
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
System.out.println("JwtAuthenticationFilter.doFilterInternal is working");
if(request.getServletPath().equals("/auth/login")) {
System.out.println("if there is a request to /auth/login just continue");
filterChain.doFilter(request, response);
}
// else continue to check JWT token
}
}
my endpoint
@AllArgsConstructor
@RestController("/auth")
public class LoginController {
private final AuthenticationManager authenticationManager;
@PostMapping("/login")
public LoginTokenResponse login(@RequestBody LoginRequest loginRequest) {
System.out.println("login method is working");
if(loginRequest == null) {
throw new IllegalArgumentException("No credentials provided");
}
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
// do other things and return LoginResponseToken
return null;
}
@GetMapping("/ping")
public String ping() {
System.out.println("pong is working");
return "pong";
}
}
and WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final PasswordCheckUserDetailService passwordCheckUserDetailService;
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(passwordCheckUserDetailService)
.passwordEncoder(UserPasswordEncoder.getUserPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers(HttpMethod.POST, "/auth/login/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter();
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
and when I make post request to /auth/login I'm getting below response and login method is not working at all. (Doesn't print)
{
"timestamp": "2022-03-12T00:59:38.932 00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/auth/login"
}
if you want to inspect other parts: https://github.com/xsenko/JWTAuthentication/tree/develop/src/main/java/com/senko/JWTAuthentication
CodePudding user response:
@RestController("/auth")
- it's for a logical component name, not for request mapping.
You should use @RequestMapping("/auth")