У меня есть установка приложения Spring Boot, использующая SpringSecurity и OneLogin в качестве поставщика токенов JWT.
Класс WebConfig выглядит следующим образом:
@EnableResourceServer
@EnableWebSecurity
@Configuration
public class WebConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
web.ignoring().mvcMatchers(
"/actuator/info",
"/actuator/health",
"/someArbitraryPath/**");
}
}
Пока все хорошо, все конечные точки, кроме указанных выше, защищены и работают только при передаче (действительного) токена JWT. Сконфигурированные выше, похоже, работают, когда вообще не передают заголовок аутентификации, что я и собираюсь сделать.
За исключением ... когда один из обоих вызовов в "/ someArbitraryPath / someDto /" генерирует исключение, которое настроено для возврата ResponseStatus "NOT_FOUND", я получаю 401 в результате.
Итак, в "/ someArbitraryPath" у меня есть следующий (открытый для общественности) контроллер REST:
@RestController
@RequestMapping("/someArbitraryPath")
public class SomeArbitraryApiController {
private final SomeArbitraryService service;
private final SomeArbitraryDtoMapper dtoMapper;
public SomeArbitraryApiController(SomeArbitraryService service, SomeArbitraryDtoMapper dtoMapper) {
this.service = service;
this.dtoMapper = dtoMapper;
}
@GetMapping(value = "/someDtosList", params = {"page", "size"})
@Transactional(readOnly = true)
public SomePageDto getSomeDtoPage(
@RequestParam(value = "page", required = false, defaultValue = "0") int page,
@RequestParam(value = "size", required = false, defaultValue = "250") int size) {
Page<SomeObject> someDtoPage = service.searchPageOfSomeObjects(page, size);
List<SomeDto> someDtoList = dtoMapper.someObjectsToDtos(someDtoPage.getContent());
PageDto pageDto = new PageDto(size, someDtoPage.getTotalElements(), someDtoPage.getTotalPages(), page);
return new SomePageDto(someDtoList, pageDto);
}
@GetMapping("/someDtosList/{dtoId}")
@Transactional(readOnly = true)
public SomeDto getSomeDtoById(@PathVariable(value = "dtoId") String dtoId) {
return dtoMapper.objectToDto(
service.getSomeObjectById(dtoId)
);
}
}
Последний вызов обоих, тот, который извлекает определенный объект SomeDto, может вызвать ResourceNotFoundException, который настроен для возврата ResponseStatus NOT_FOUND:
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String resourceName, String fieldName, Object fieldValue) {
super(String.format("%s not found with %s : '%s'", resourceName, fieldName, fieldValue));
}
}
Это, однако, НЕ возвращает HTTP-статус 404 при вызове этого незащищенного - это возвращает мне 401 Несанкционированный:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
Однако, когда я явно перехватываю исключение в моем RestController и устанавливаю статус ответа для объекта HttpServletResponse равным
response.setStatus(HttpStatus.SC_NOT_FOUND);
тогда я получаю 404. Но не тот, который я хотел бы (и я бы не хотел перенастраивать тот же объект ошибки, не так ли).
Когда я вызываю эту конечную точку с действительным токеном JWT, он возвращает мне правильную ошибку 404. Правильное тело.
Что я делаю не так?