Пользовательские заголовки, заблокированные CORS

Я делаю запросы с помощью приложения Angular2+ к API NodeJS.

Пока я не добавляю пользовательские заголовки, звонки выполняются, и я получаю ответ в соответствии с моим запросом. Но если у меня был заголовок вручную с использованием interceptor, это приводит к ошибке.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at [api_url]. (Reason: CORS request did not succeed)

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

Пользовательские заголовки, заблокированные CORS

Заголовки первого метода POST

Пользовательские заголовки, заблокированные CORS

И один из второго метода POST

Пользовательские заголовки, заблокированные CORS

Два пользовательских заголовка добавляются перехватчиком в Angular следующим образом.

...
const cloned = req.clone({
  headers: req.headers.set("Authorization", "Bearer " + idToken)
                      .set("X-QWEMP-data", encrypted)
});
req = cloned
...

И когда я их удаляю, маршрут достигается, но, естественно, выдает ошибку из-за отсутствия данных.

Что касается моего API, я перепробовал множество конфигураций, позволяющих использовать настраиваемые заголовки. Сначала нужно было добавить заголовки и вернуть ОПЦИИ предварительной проверки вручную, как показано ниже (не помню точно, как я это сделал, но что-то вроде этого)

app.use((req,res,next) => {
  set.headers('Access-Control-Allow-Origin','*')
  set.headers('Access-Control-Allow-Headers','Authorization,X-QWEMP-data')
  if (req.method === 'OPTIONS') {
    res.send()
    return;
  }else{
    next()
    return;
  }
})

Затем я использовал библиотеку cors и конфигурацию по умолчанию, просто добавив app.use(cors())

И, наконец, я попытался добавить пользовательскую конфигурацию в cors, например, следовать (весь файл app.js)

require('dotenv').config()
const express = require('express');
const indexRouter = require('../routes/index');
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan');

const app = express();

app.use(cors({
  methods:'GET,POST,PUT,DELETE,OPTIONS',
  allowedHeaders:'Authorization,X-QWEMP-data,Content-Type,[and all the already accepted headers in case]',
  exposedHeaders:'[same as allowedHeaders]',
  credentials:true,
  preflightContinue:true
})

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.use(morgan('tiny'));

app.use('/', indexRouter)

app.listen(3000, () => {
  console.info('Server listening on port 3000.')
})

РЕДАКТИРОВАТЬ

Экраны запросов во вкладке сети

Первый ВАРИАНТ

Пользовательские заголовки, заблокированные CORS

Первый пост

Пользовательские заголовки, заблокированные CORS

Второй вариант

Пользовательские заголовки, заблокированные CORS

Второй пост

Пользовательские заголовки, заблокированные CORS

См. stackoverflow.com/a/48133489/441757 и npmjs.com/package/cors#enbling-cors-pre-flight. Вам нужно добавить некоторую форму app.options('*', cors()) в код сервера.

sideshowbarker 19.03.2022 10:11

@alexis, вы заметите в документе cors, что app.use(cors()) по умолчанию не обрабатывает запросы OPTIONS, поскольку методы по умолчанию: "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",. См. документ здесь.

jfriend00 19.03.2022 10:18

@sideshowbarker, я тестировал app.options('*', cors()) перед другими маршрутами, но не помогает. @ jfriend00, я добавил метод «OPTIONS» в конфигурацию cors, как вы можете видеть в вопросе.

Alexis 19.03.2022 16:48

Я смущен здесь. То, что вы пометили как First OPTION и First POST, успешно выполнено. Эти запросы выполняются успешно. First OPTION — это статус 204 (как и ожидалось), а First POST — это 200. Похоже, это работает. Я не знаю, достиг ли он желаемого кода маршрута сервера, но оба запроса возвращают успешные HTTP-ответы с сервера.

jfriend00 19.03.2022 18:13

То, что вы пометили как второй вариант, похоже, тоже работает (статус 204). Кажется, что второй POST никогда не отправляет ответ с сервера, или вы что-то упускаете из снимка экрана (без статуса и без заголовков ответа).

jfriend00 19.03.2022 18:15

В этом проблема, как я сказал в начале своего вопроса, пока я не добавляю пользовательские заголовки, все в порядке, но если я добавлю пользовательский заголовок в запрос с помощью перехватчика или чего-либо еще, я просто не могу получить результат из-за CORS. Итак, здесь в моем методе я делаю 2 вызова на сервер, первый простой и не требует никаких пользовательских заголовков, поэтому все в порядке, а второй требует пользовательских заголовков и выдает ошибку.

Alexis 19.03.2022 18:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
34
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Добавление настраиваемого заголовка приводит к тому, что браузеру требуется предварительная проверка для запроса между источниками. Это означает, что браузер отправит запрос OPTIONS на ваш сервер по тому же пути и должен вернуть ответ 2xx с соответствующими заголовками из этого запроса OPTIONS, иначе он не отправит фактический последующий запрос.

Из того, что я могу сказать в документе для модуля CORS (и проверено небольшим экспериментом), когда вы устанавливаете:

preflightContinue: true

Вы говорите промежуточному программному обеспечению COR пропустить этот запрос OPTIONS и отправить его другим обработчикам запросов. В документе конкретно сказано: «Передать предварительный ответ CORS следующему обработчику». Поскольку у вас нет других обработчиков запросов для этого предварительного запроса, ваш сервер сгенерирует 404, и браузер увидит, что предварительная проверка не удалась, поэтому ваш запрос не будет выполнен.

Итак, первое, что нужно попробовать, это изменить на:

preflightContinue: false

Если это все еще не работает, покажите точный запрос, как показано на вкладке сети отладчика Chrome. Он точно покажет, что браузер отправляет для предварительной проверки, и точно покажет, что ваш сервер возвращает в ответ на это.

Спасибо, но это не делает его лучше. На самом деле я уже пробовал с false, но я написал пример с true. Я отредактировал вопрос с нужными вам скринами.

Alexis 19.03.2022 17:02
Ответ принят как подходящий

В конце концов, проблема была не в CORS, даже если он выдавал ошибку.

На самом деле JWT был слишком длинным по неизвестной причине. Я использовал «Burp Suite» для перехвата запросов и добавил запрос в повторитель, чтобы повторно отправить их и протестировать с пользовательскими значениями.

Чтобы понять это, мне нужно было обновить ключ, используемый библиотекой jsonwebtoken, чтобы подписать JWT, на меньший ключ, и таким образом JWT был меньше.

Другие вопросы по теме