Заголовок авторизации не отправляется в запросе из разных источников

Решение в КОНЦЕ.

Моя проблема была в моем сервере ... Вскоре решение, мне нужно использовать экспресс-корс

Исходное сообщение:

Прежде всего:
Я добавил Access-Control-Allow-Origin, Access-Control-Allow-Headers, и я могу получить доступ к серверу, но я не могу отправлять данные в Заголовок на сервер.

Итак:
Я работаю в основном с Vue.js (с webpack для горячей перезагрузки изменений) и Express (с nodemon). Итак, у меня есть 2 отдельных сервера:

  • Во-первых: бэкэнд (сервер), работающий по адресу: http://localhost:3000 с nodemon
  • Во-вторых: интерфейс (клиент), работающий по адресу: http://localhost:8080 с webpack-dev-сервером (для горячей перезагрузки изменений vuejs), он будет разрабатываться в одностраничном приложении.

На моем сервере есть аутентификация с помощью паспорта.js с использованием токена jwt (в этой статье показано, как: аутентификация vuejs и токен jwt экспресс-паспорта). Но не в этом суть, просто чтобы объяснить.

Когда я делаю запрос (используя axios, fetch, не имеет значения), когда я отправляю запрос к своему API из http://localhost:8080 (порт 8080, webpack) на сервер по адресу http://localhost:3000/api/products они не сделали ' t получать заголовок Authorization.

Если я делаю запрос с того же сервера, от http://localhost:3000/index.html (порт 3000) к серверу по адресу http://localhost:3000/api/products, они получают заголовок Authorization.

Не знаю почему!

На сервере я реализую политику CORs следующим образом:

//(...)
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, access-control-request-headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, authorization, Access-Control-Allow-Credentials, X-Auth-Token, X-Accept-Charset,X-Accept");
  //res.header("Access-Control-Allow-Headers", "*");
  
  //res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
//(...)

У клиента отправляю заголовок:

  // (...) Imports
  import axios from "axios";

  // (...) other code
  const http = axios.create ({
    baseURL: process.env.VUE_APP_ROOT_API,
    timeout: 1000,
    withCredentials: true,
    headers: {'Content-Type': 'application/json'},
  });

  /*   // -- I Have tried this too...
  http.interceptors.request.use (
    function (config) {
      if (token) config.headers.Authorization = `Bearer ${token}`;
      return config;
    },
    function (error) {
      return Promise.reject (error);
    }
  );      
  */

  http.get('http://localhost:3000/api/products', {headers : { authorization: `Bearer ${token}` } }).then(data => {

// (...) code after

Когда я тестирую на том же сервере, он работает, когда на отдельном сервере они не отправляют заголовок на сервер.

Вот гифка, показывающая проблему:

gif

ПРИМЕР КОДА ДЛЯ ТЕСТИРОВАНИЯ ПРОБЛЕМЫ: https://github.com/dennnisk/cors_police_response_preflight_does_not_have_http_ok.git

Я застрял...


** РЕДАКТИРОВАТЬ 1 **:

Я меняю часть кода os axios, добавляя withCredentials: true,, как было предложено, но получаю ошибку: Access to XMLHttpRequest at 'http://localhost:3000/api/products' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

Итак, я меняю сервер app.js с этого:

(...)
app.use(function(req, res, next) {
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
(...)

К этому:

(...)
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', "http://localhost:8080/");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

(...)

И получите эту ошибку: Access to XMLHttpRequest at 'http://localhost:3000/api/products' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

Думаю, что-то не так с конфигом сервера ...


ИЗМЕНИТЬ 2:

Это был мой сервер. Необходимо использовать экспресс-корс Размещен ответ ниже ...


person dennnis    schedule 03.01.2019    source источник
comment
Если вы не установите withCredentials: true для вызова axios.get в коде внешнего интерфейса, браузер не отправит заголовок авторизации.   -  person sideshowbarker    schedule 03.01.2019
comment
Спасибо! Я только что попробовал, но не работает. :( .. Я меняю и получаю сообщение об ошибке: Access to XMLHttpRequest at 'http://localhost:3000/api/products' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.. Я думаю, что на сервере не работает somenthing. Я пытался изменить с res.header('Access-Control-Allow-Origin', "*"); на res.header('Access-Control-Allow-Origin', "http://localhost:8080");, но это не сработало.   -  person dennnis    schedule 03.01.2019


Ответы (2)


Вы забыли добавить withCredentials: true в аксиомах?

const myrequests = axios.create({
  withCredentials: true,
  ...
})

и после этого:

myrequests.get('http://localhost:3000/api/products', {headers : { 
  authorization: `Bearer ${token}` } })
  .then((data) => { 
   // REST OF THE CODE
  })
// (...) code after
person ƒernando Valle    schedule 03.01.2019
comment
Должно быть хорошо, если вы добавите конфигурацию myrequests в другой файл и импортируете в main.js вместо импорта axios как она. - person ƒernando Valle; 03.01.2019
comment
Я пробовал это. Но не работает. Я думаю, что на сервере что-то не так. Я отредактирую пост и дополню вопрос этим и новой ошибкой ... - person dennnis; 03.01.2019

Решение проблемы

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

//(...)
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', "*");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Credentials', 'true');
  res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, access-control-request-headers, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, authorization, Access-Control-Allow-Credentials, X-Auth-Token, X-Accept-Charset,X-Accept");
  next();
});
//(...)

1. Я устраняю это и устанавливаю cors yarn add cors --save (или _3 _)
2 - Добавить требование для корса:

 var express = require('express');
 var cors = require('cors');  ///  <<======= Add here
 var path = require('path');

3 - Используйте cors перед моим методом «аутентификации», например:

// get authenticated data
app.use('/api/products', cors({credentials: true, origin: 'http://localhost:8080'}), isAutenticated(), function(req, res, next) {
  res.json({id: '1000', text: 'test'});
});

Вот и все. Работает нормально ... наконец-то спустя почти 2 дня ...

Я подтверждаю решение по адресу: https://github.com/dennnisk/cors_police_response_preflight_does_not_have_http_ok

person dennnis    schedule 03.01.2019
comment
Да, вероятно, проблема заключалась в порядке установки промежуточного программного обеспечения для CORS, который должен быть перед методом аутентификации (если это паспорт, он должен быть одним из последних). - person ƒernando Valle; 04.01.2019