Ошибка CORS только от Angular, а не от Chrome Extension, который не является Angular - PullRequest
0 голосов
/ 17 сентября 2018

Я очень смущен ошибкой, которую мы получаем с новым приложением Angular6.У нас есть существующий API, написанный на ASP.NET Core 2, и мы без проблем использовали этот API из расширения Chrome, написанного на Typescript, который отправляет данные следующим образом:

    let login: any = {
        username: options.userName,
        password: options.password
    };

    let body: string = JSON.stringify(login);
    return fetch(`${environment.jwtApiUrl}/api/token`,
        {
            method: "POST",
            headers: {
                'Accept': 'application/json',
                "Content-Type": "application/json"
            },
            body: body
        });

Теперь мы потребляем точно такое жеAPI из нашего приложения Ionic 4 Angular выглядит так:

export class AuthenticationService {
  constructor(
    private http: HttpClient,
    private storage: Storage) { }

  public isLoggedIn(): boolean {
    return this.storage.get("token") != null;
  }

  public async login(username: string, password: string): Promise<boolean> {

    let login: any = {
      username: username,
      password: password
    };

    let body: string = JSON.stringify(login);

    var result = await this.http.post<any>(`${environment.jwtApiUrl}/api/token`, body).toPromise();
    if (result && result.token) {
      this.storage.set("token", result.token);
      return true;
    };

    return false;
  }

  logout() {
    // remove user from local storage to log user out
    this.storage.remove('token');
  }
}

В приложении Angular мы используем HttpInterceptor:

export class JwtInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    console.log("JwtInterceptor");
    let token = JSON.parse(localStorage.getItem('token'));
    if (token) {
        request = request.clone({
            setHeaders: { 
                "Authorization": `Bearer ${token}`
            }
        });
    }

    if (!request.headers.has('Content-Type')) {
        request = request.clone({ headers: request.headers.set('Content-Type', 'application/json') });
    }

    console.log(request);
    return next.handle(request);
}
}

В Angular POST становится запросом OPTIONS, и мы получаем404 не найдено и:

Не удалось загрузить https://oururl/api/token: Ответ на предпечатный запрос не проходит проверку контроля доступа: заголовок «Access-Control-Allow-Origin» отсутствует назапрашиваемый ресурс.Поэтому Origin 'http://localhost:8100' не имеет доступа.

Почему мы получаем это только из Angular, а не из расширения Chrome, которое также выполняет междоменные вызовы и работает ли оно в любом случае?вокруг этого, кроме включения Cors в API?

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

У меня была такая же проблема, но я не хотел менять настройку CORS на моем сервере. Я решил эту проблему во время разработки, создав приложение api bridge node.js и запустив его на своем сервере. У Node есть возможность настроить CORS в файле (который является сервером), затем я использовал узел, чтобы сделать запрос API и передать его моему угловому приложению (во время разработки). Или это, или как в предыдущем ответе сказано: включите CORS для вас api (или sever).

0 голосов
/ 17 сентября 2018

CORS применяется только в браузерах, и поэтому все остальное не затронет проблемы CORS.

Предварительный запрос OPTIONS - это запрос проверки того, что ваш сервер принимает запросы CORS перед тем, как выполнить настоящий запрос POST. Если запросы OPTIONS обнаружат, что сервер имеет необходимые CORS заголовки , он выполнит запрос POST. В противном случае он даже не сделает запрос POST (почему он должен тратить свое время, делая запрос, если он уже знает из запроса OPTIONS, что у него нет разрешения от сервера на это).

Есть 2 подхода для решения этой проблемы:

(1) Добавьте соответствующий заголовок CORS к ответу сервера, убедившись, что сервер принимает PUT POST DELETE GET OPTIONS (и, возможно, HEAD)

(2) Используйте прокси для перезаписи URL. Браузер отправляет запрос к конечной точке в том же домене и порту (таким образом избегая CORS), а сервер, обслуживающий ваше приложение Angular, переписывает запрос в другой домен и порт. Для среды разработки вы можете запустить webpack для запросов прокси таким образом с флагом --proxy-config (Webpack используется Angular CLI под капотом). Используйте флаг --proxy-config в стартовом скрипте npm. Вам нужно будет воспроизвести эту конфигурацию на вашем сервере Prod.

Для (2) на вашем dev-сервере создайте файл с именем proxy.json следующим образом:

{
  "/api": {
    "target": "http://localhost:9000",
    "secure": false
  }
}

И запустите ваш сервер Angular CLI с помощью:

ng serve --proxy-config ./proxy.json

Эта конфигурация в основном говорит прокси любой запрос, начинающийся с / api в пути к целевому домену и порту.

Как я уже сказал, вам нужно будет повторить это на вашем сервере prod, который зависит от того, какой сервер вы используете в prod. Вам также необходимо убедиться, что все вызовы API начинаются с / api в пути.

0 голосов
/ 17 сентября 2018

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

Одно из предположений о том, что ваше расширение Chrome сработало, - возможно, расширение не имеет таких же (безопасности) ограничений, как браузер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...