Рубрики
Без рубрики

Фиксация 401s с помощью предварительных фар CORS и пружинной защиты

Узнайте, как исправить состояние ошибки HTTP 401 для предполетных запросов CORS

Автор оригинала: baeldung.

1. Обзор

В этом коротком уроке мы узнаем, как устранить ошибку “Ответ на предполетный запрос имеет недопустимый код состояния HTTP 401”, которая может возникать в приложениях, поддерживающих связь между источниками и использующих Spring Security.

Во-первых, мы посмотрим, что такое запросы перекрестного происхождения, а затем исправим проблемный пример.

2. Запросы Перекрестного Происхождения

Короче говоря, запросы перекрестного происхождения-это HTTP-запросы, в которых источник и цель запроса различны. Это имеет место, например, когда веб-приложение обслуживается из одного домена, а браузер отправляет запрос AJAX на сервер в другом домене.

Для управления запросами между источниками сервер должен включить определенный механизм, известный как CORS, или совместное использование ресурсов между источниками.

Первым шагом в CORS является запрос OPTIONS , чтобы определить, поддерживает ли его цель запроса. Это называется запросом перед полетом.

Затем сервер может ответить на запрос перед полетом набором заголовков:

  • Access-Control-Allow-Origin : Определяет, какие источники могут иметь доступ к ресурсу. “*”представляет любое происхождение
  • Access-Control-Allow-Methods : Указывает разрешенные методы HTTP для запросов перекрестного происхождения
  • Access-Control-Allow-Headers : Указывает разрешенные заголовки запросов для перекрестных запросов
  • Access-Control-Max-Age : Определяет время истечения срока действия результата кэшированного предполетного запроса

Таким образом, если предполетный запрос не соответствует условиям, определенным из этих заголовков ответов, фактический последующий запрос вызовет ошибки, связанные с запросом перекрестного происхождения.

Это легко сделать добавьте поддержку CORS в наш сервис с пружинным питанием , но если он настроен неправильно, этот запрос перед полетом всегда завершится ошибкой с 401.

3. Создание REST API с поддержкой CORS

Чтобы смоделировать проблему, давайте сначала создадим простой REST API, который поддерживает запросы из разных источников:

@RestController
@CrossOrigin("http://localhost:4200")
public class ResourceController {

    @GetMapping("/user")
    public String user(Principal principal) {
        return principal.getName();
    }
}

Аннотация @CrossOrigin гарантирует, что наши API доступны только из источника, указанного в ее аргументе.

4. Защита Нашего API REST

Теперь давайте защитим наш REST API с помощью Spring Security:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .httpBasic();
    }
}

В этом классе конфигурации мы применили авторизацию ко всем входящим запросам. В результате он отклонит все запросы без действительного маркера авторизации.

5. Выполнение предполетного запроса

Теперь, когда мы создали наш REST API, давайте попробуем выполнить запрос перед полетом с помощью curl :

curl -v -H "Access-Control-Request-Method: GET" -H "Origin: http://localhost:4200" 
  -X OPTIONS http://localhost:8080/user
...
< HTTP/1.1 401
...
< WWW-Authenticate: Basic realm="Realm"
...
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: http://localhost:4200
< Access-Control-Allow-Methods: POST
< Access-Control-Allow-Credentials: true
< Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
...

Из вывода этой команды мы видим, что запрос был отклонен с 401.

Поскольку это команда curl , мы не увидим ошибку “Ответ на предполетный запрос имеет недопустимый код состояния HTTP 401” в выходных данных.

Но мы можем воспроизвести эту точную ошибку, создав интерфейсное приложение, которое использует наш REST API из другого домена, и запустив его в браузере.

6. Решение

Мы явно не исключили предполетные запросы из авторизации в нашей конфигурации безопасности Spring . Помните, что Spring Security по умолчанию защищает все конечные точки.

В результате наш API также ожидает маркер авторизации в запросе ОПЦИЙ.

Spring предоставляет готовое решение для исключения запросов параметров из проверок авторизации:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // ...
        http.cors();
    }
}

Метод cors() добавит предоставленный Spring CorsFilter в контекст приложения, который, в свою очередь, обходит проверки авторизации для запросов опций.

Теперь мы можем снова протестировать ваше приложение и убедиться, что оно работает.

7. Заключение

В этой короткой статье мы узнали, как исправить ошибку “Ответ на предполетный запрос имеет недопустимый код состояния HTTP 401”, которая связана с запросами Spring Security и cross-origin.

Обратите внимание, что в приведенном примере клиент и API должны работать в разных доменах или портах, чтобы воссоздать проблему. Например, мы можем сопоставить имя хоста по умолчанию клиенту и IP-адрес машины с нашим REST API при работе на локальной машине.

Как всегда, пример, показанный в этом учебнике, можно найти на Github .