Почему добавление перехватчика HTTP вызывает ошибки CORS? - PullRequest
0 голосов
/ 05 февраля 2019

Я разрабатываю приложение Angular 6 с PHP REST Api.Моя среда разработки размещена на моем локальном хосте, поэтому для начала мне пришлось включить Access-Control-Allow-Origin: * для обхода любых ошибок CORS, которые я получал.

Недавно я пытался реализоватьJWT с перехватчиком, чтобы добавить их в мои запросы HTTP.Как только я включил интерпретатор следующих примеров из Google, я снова начал получать ошибку CORS:

blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header

Я уверен, что это связано с моим перехватчиком, потому что, когда я его комментирую, он снова работает,Вот код для перехватчика, с которым я хотел бы работать:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from 
'@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/index';
import {AuthService} from './auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(public auth: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): 
Observable<HttpEvent<any>> {
    req = req.clone({
      setHeaders: {
         'Content-Type' : 'application/json; charset=utf-8',
        // 'Accept'       : 'application/json',
        'Authorization': `Bearer ${this.auth.getToken()}`
      }
    });

    return next.handle(req);
  }
}

Я даже попытался сократить его, чтобы просто установить заголовок Авторизации для использования.

Если я комментируюиз заголовка авторизации и просто оставить Content-Type, я все еще получаю ошибку CORS.Если я изменяю Content-type на обычный / текстовый, он работает, но тогда у меня нет заголовка авторизации.Если я сохраняю тип контента в обычном / текстовом формате и добавляю заголовок авторизации, я получаю ошибку CORS.

На данный момент я просто хочу увидеть заголовок авторизации в переменной $ _SERVER, поэтому PHP довольно просто проверить:

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, 
OPTIONS');
header('Access-Control-Allow-Headers: Authorization, Access, Origin, 
Content-Type, X-Auth-Token');

echo json_encode(array(
        'status' => 0
        ,'message'=> $_SERVER
    ));

exit;

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

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginFormComponent } from './login-form/login-form.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {AuthInterceptor} from './auth.interceptor';
import { MessagesComponent } from './messages/messages.component';

@NgModule({
  declarations: [
    AppComponent,
    LoginFormComponent,
    MessagesComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

А вот служба входа, которую я использую для отправки HTTP-запроса:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ServerResponse } from './server-response';
import {MessagesService} from './messages.service';
import {AuthService} from './auth.service';

@Injectable({
  providedIn: 'root'
})

export class LoginService {

  constructor(private http: HttpClient,
              private ms: MessagesService,
              private auth: AuthService) { }
  login(formData) {
    this.ms.clear();
    console.log('JSON data', JSON.stringify((formData)));
    console.log(this.auth.getToken());
    return this.http.post('http://jpapp.com/api/login/login.php',     JSON.stringify(formData))
      .subscribe((rs: ServerResponse) => {
        console.log('%cPost Success', 'color: green;');
        console.log(rs);
    }, (error) => ({status: -99, message: error}));
  }
}

Если я удаляю перехватчик, заголовок Requet выглядит следующим образом (вот где у меня появилась идея попробовать изменить тип содержимого на обычный / текстовый):

Provisional headers are shown
Accept: application/json, text/plain, */*
Content-Type: text/plain
Origin: http://localhost:4200
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

И когда у меня включен перехватчик, заголовок запроса выглядит так:

Provisional headers are shown
Access-Control-Request-Headers: authorization,content-type
Access-Control-Request-Method: POST
Origin: http://localhost:4200
Referer: http://localhost:4200/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 
(KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

Я читал, что могу обойти это с расширением chrome, но хотел узнать, есть ли что-то в моем коде, прежде чем пытаться установить расширения.

Любая информация приветствуется!

1 Ответ

0 голосов
/ 06 февраля 2019

Обновление

edit : Я должен упомянуть причину, по которой установка req.clone () для пустых работ, которую я обнаружил, заключается в том, что предполёт происходит только на complex в отличие от простых запросов cors.Как только вы добавляете пользовательский заголовок, в моем случае Authorization или делаете что-либо, что делает его больше не простым запросом, он по умолчанию отправляет предварительный запрос методом OPTIONS вместо, в моем случае, POST.Эта статья отлично объясняет cors и простой и сложный запрос: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Ошибка ответа перед проверкой не имеет ничего общего с самим кодом.Проблема была с настройкой моего веб-сервера IIS 10.

После этой статьи: Справочник по настройке модуля CORS Я добавил необходимые узлы cors в свой файл web.config, и теперь он работаетправильно

Мне удалось обойти ошибку CORS запроса предполета, установив Allow-Control-Allow-Origin: * Расширение Chrome https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

Кажется, все еще работает, только еслиЯ сохраняю URL-адрес по умолчанию, соответствующий *://*/*, если я изменяю его, чтобы он соответствовал моим URL-адресам, я снова получаю ошибку CORS, но это может быть просто проблемой с моим сопоставлением с шаблоном.Было бы неплохо, если бы было объяснение, как это работает.

Я все еще ищу причину того, почему передача авторизации через перехватчик нарушает работу серверов Access-Control-Allow-Origin: * asЯ уверен, что столкнусь с этой проблемой снова, как только разверну это приложение и API.Это также PITA для использования этого расширения с конфигурацией по умолчанию, так как оно сломает множество сайтов.

...