У меня есть Spring Boot Rest API, который выполняет некоторую фильтрацию проверки, прежде чем разрешить запрос запрошенному методу. Когда он попадает в запрошенную конечную точку, я провожу некоторую проверку данных, отправленных на сервер, и хочу вернуть ответ ПЛОХОЙ ЗАПРОС, если данные не отформатированы должным образом. Однако попытка выбросить Springs ResponseStatusException не работает, вместо этого он всегда возвращает 403 Forbidden, и я понятия не имею, почему.
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
JWTUtility jwtUtility;
@Autowired
UserRepository repository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager(), jwtUtility, repository))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.POST, "/users");
}
}
.
@RestController
@RequestMapping("/users")
@Slf4j
public class UserController {
private final UserRepository repository;
private final Pbkdf2PasswordEncoder passwordEncoder;
UserController(UserRepository repository, Pbkdf2PasswordEncoder passwordEncoder, JWTUtility jwtUtility) {
this.repository = repository;
this.passwordEncoder = passwordEncoder;
this.jwtUtility = jwtUtility;
}
@PostMapping
User create(@RequestBody User user) {
if (user.getFirstName() == null || user.getFirstName().isEmpty()
|| user.getLastName() == null || user.getLastName().isEmpty()
|| user.getEmail() == null || user.getEmail().isEmpty()
|| user.getDisplayName() == null || user.getDisplayName().isEmpty()
|| user.getPassword() == null || user.getPassword().isEmpty()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "First name, last name, email, display name, and password must be provided when creating a new user.");
}
if (repository.findByEmail(user.getEmail()) != null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "A user with that email already exists");
}
if (repository.findByDisplayName(user.getDisplayName()) != null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "A user with that display name already exists");
}
user.setId(0);
user.setPassword(passwordEncoder.encode(user.getPassword()));
repository.save(user);
return user;
}
}
Я ожидал, что плохой запрос вернется к пользователю с описанием, которое я предоставил. Spring где-то это перехватывает? И как мне это остановить.
Это странно, он нигде не генерирует трассировку стека. Как только он попадает в мой бросок, он просто возвращает 403.
Комментирование @EnableWebSecurity приводит к тому, что он никогда не достигает моей конечной точки, а вместо этого просто возвращает 401 Unauthorized.




Оказывается, это была проблема с конфигурацией безопасности, в то время как у меня конечная точка /users игнорировалась в конфигурации веб-безопасности, разрешая запрос до метода, по-видимому, вызывая исключение в этом методе, что привело к включению безопасности HTTP и его перехвату.
Поэтому, изменив мою http-безопасность, чтобы она выглядела так,
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/users").permitAll()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager(), jwtUtility, repository))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
решил вопрос. Странно, что он ведет себя так, поскольку, если запрос выполнен успешно и мне не нужно генерировать исключение, пользовательский объект возвращается нормально. Кажется, что выброс исключения заставил его обратить внимание не только на веб-безопасность, но и на безопасность http.
Можете ли вы распечатать исключения стека вашей службы отдыха?