Ответ на предполетный период не имеет статуса HTTP ok в угловом

У меня есть следующий запрос на получение, указанный в моей службе:

createAuthorizationHeader(user, pass) {
  let headers: HttpHeaders = new HttpHeaders;
  headers = headers.append('Accept', 'application/json, text/plain, */*');
  headers = headers.append('Authorization', 'Basic ' + btoa(user + ':' + pass));
  headers = headers.append('Content-Type', 'application/json; charset=utf-8');
    console.log(headers);
    return this.http.get(this._loginUrl, {
      headers: headers
    });
}

Результат:

OPTIONS https://localhost:8443/delivery/all 401 ()

Failed to load https://localhost:8443/delivery/all: Response for preflight does not have HTTP ok status.

HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}

Я также сделал тот же пост-запрос с Postman, но все работает, поэтому работает локальный сервер.

Я не могу понять, что я делаю неправильно с моей просьбой.

Ответ 1

Контракт CORS требует, чтобы аутентификация не требовалась по запросу перед полетом OPTIONS. Похоже, ваш сервер требует аутентификации в запросе OPTIONS и GET.

Когда вы обращаетесь к своему серверу с помощью Postman, вы отправляете GET только. Браузер сначала отправит запрос OPTIONS (без заголовка проверки подлинности), и попросит ответ получить заголовок "Access-Control-Allow-Origin", который соответствует началу страницы, задающей запрос.

Если ответ на ответ OPTIONS не является 2xx или заголовок отсутствует, или значение заголовка не соответствует запрашиваемому началу страницы, вы получите сообщение об ошибке, которое вы испытываете, и запрос GET не будет сделан,

TL;DR; измените исходный код, чтобы не требовать аутентификации для метода OPTIONS при обработке URL-адреса входа.

Ответ 2

По умолчанию браузеры не позволяют пользователям выполнять перекрестный запрос.

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

Предположим, что угловой пользовательский интерфейс работает на localhost: 4200 и хочет вызвать URL-адрес остальной конечной точки, например: https://localhost: 8443/delivery/all

Следующие шаги помогут решить эту проблему.

  1. Создайте файл proxy.config.json в корневой папке вашего углового приложения. (Там, где существует файл package.json) Прокси-сервер просто берет запрос браузера на тот же домен + порт, на котором запускается ваше веб-приложение, а затем перенаправляет этот запрос на ваш бэкэнд-сервер API. CORS - это проблема безопасности браузера, которая не применяется при взаимодействии "бэкэнд-бэкэнд", как в случае промежуточного прокси-сервера.

    Содержание должно выглядеть следующим образом.

    Образец:

    {
        "/delivery/all/*": {
        "target": "https://localhost:8443",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true
        }
    }
    

    Все запросы, сделанные к /delivery/all/... из нашего приложения, будут перенаправлены на https://localhost: 8443/delivery/all/

    Примечание: свойство changeOrigin. Вам определенно придется установить значение true, когда вы используете некоторые виртуальные прокси (например, настроенные с помощью Apache2) на вашем бэкэнде

  2. Добавить конфигурацию прокси при запуске приложения. Angular поддерживает "--proxy-config", где вы можете указать файл конфигурации прокси. Если вы используете опцию "npm start" для тестирования, вы должны добавить опцию "--proxy-config", как указано ниже. Он должен быть добавлен в файл package.json.

     "scripts": {
    
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.config.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
    }
    

    Если вы работаете напрямую, используя "ng serve", то оно будет изменено, как указано ниже. "ng serve --proxy-config proxy.config.json"

  3. HTTP-вызов внутри нашего приложения Angular можно изменить на это. Сервер автоматически перенаправит запрос на " https://localhost: 8443/delivery/all ".

    this.http.get(' https://localhost: 8443/delivery/all ').map(res => res.json());

    в

    this.http.get('/delivery/all').map(res => res.json());

вот ссылка для получения дополнительной информации: https://sudhasoftjava.wordpress.com/2018/10/05/proxy-configuration-in-angular/

Ответ 3

@Daryl

Что мы сделали, так это добавить пользовательскую конфигурацию для Cors. А затем включите его через конфигурацию безопасности на java-сервере. Этот Сервер был включен только для прямых вызовов REST, как объяснено в ответе.

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                        .allowedHeaders("*");
            }
        };
    }
}

И это входит в конфигурацию веб-безопасности:

@Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
                .antMatcher("/**")
                .authorizeRequests().and()
                .httpBasic()
                .and()
                .authorizeRequests().anyRequest().authenticated().and().cors();
    }