AWS API Gateway - CORS "access-control-allow-origin" - несколько записей

У меня есть экземпляр AWS Lambda, который подключается к определенному шлюзу API AWS. Если я включу CORS и дам access-control-allow-origin определение http://example.comтогда я могу получить доступ к экземпляру Lambda из http://example.com, Однако, если я использую https://example.comне работает

Итак, в AWS, как я могу определить, используя несколько access-control-allow-origin значения без использования подстановочного знака? Я пытался использовать что-то вроде *.example.com, но это не работает.

РЕДАКТИРОВАТЬ: если я использую '*' как мое значение для шлюза API, но настроить правила CORS для моего сегмента S3, это будет безопасно? Пример для правил корзины:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://www.example.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

5 ответов

Решение

К сожалению, сегодня это невозможно. Спецификация CORS не допускает частичных подстановочных знаков, и в настоящее время API-шлюз допускает только одно статическое значение для заголовка.

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

Это всегда раздражало CORS, если вы хотите включить несколько источников.

Обычный обходной путь в других системах (например, express / nginx и т. Д.) Заключается в следующем:

  • осмотреть Origin заголовок, отправленный браузером
  • проверьте это против белого списка происхождения
  • если он совпадает, вернуть входящий Origin как Access-Control-Allow-Origin заголовок, иначе вернуть заполнитель (источник по умолчанию)

Это невозможно при использовании автоматической поддержки CORS в AWS-Gateway, поскольку используется фиктивная интеграция, однако это возможно, если вы напишите свой собственный код для обработки OPTIONS запрос.

Ниже приведен пример кода, написанного с использованием лямбда-прокси:

const allowedOrigins = [
    "http://example.com",
    "http://example.com:8080",
    "https://example.com",
    "https?://[a-z]*.?myapp.com",
    "http://localhost:[0-9]*"
];

exports.handler = (event, context) => {
    const origin = event.headers.Origin || event.headers.origin;
    var goodOrigin = false;

    if (origin) {
        allowedOrigins.forEach( allowedOrigin => {
            if (!goodOrigin && origin.match(allowedOrigin)) {
                goodOrigin = true;
            }
        });
    }

    context.succeed({
        headers: {
            "Access-Control-Allow-Headers": "Accept,Accept-Language,Content-Language,Content-Type,Authorization,x-correlation-id",
            "Access-Control-Expose-Headers": "x-my-header-out",
            "Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
            "Access-Control-Allow-Origin": goodOrigin ? origin : allowedOrigins[0]
        },
        statusCode: 204
    });
};

Сохраните это как лямбда-функцию. Чтобы настроить это в API-шлюзе, добавьте OPTIONS метод и для Integration Request выбирать Lambda Function с Use Lambda Proxy integration тикали.

Конечно, недостатком этого является то, что вы платите за лямбда-функции, и вызов лямбда-функции, вероятно, будет иметь дополнительную задержку в 50 мс по сравнению с ложной интеграцией.

Почему бы не использовать шаблон сопоставления языка Velocity Template для проверки из списка разрешенных доменов и установки исходного заголовка

$input.json("$")
#set($domains = ["https://www.example.com", "https://www.abcd.com"])
#set($origin = $input.params("origin"))
#if($domains.contains($origin))
#set($context.responseOverride.header.Access-Control-Allow-Origin="$origin")
#end

Я сделал что-то вроде этого:

const handler: APIGatewayProxyHandler = async (event) => {
  const origin = event?.headers?.Origin || event?.headers?.origin;
  const allowedOrigins = ['https://example.com'];
  const headers = {
    'Access-Control-Allow-Origin': allowedOrigins.includes(origin)
      ? origin
      : allowedOrigins[0],
  };

  return {
    headers,
    body: JSON.stringify({
      myResponse: 'data',
    }),
    statusCode: 200,
  };
};

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

fetch('https://exampleLambda.com/v1/example', { 
   method: 'get',
   mode: 'cors'
   headers: new Headers({
     'Authorization': 'Bearer 12345, 
   }), 
 })
 .then(result => result.json())
 .then(console.log)

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

  1. В ресурсах шлюза API щелкните любой метод OPTIONS и перейдите к запросу на интеграцию.
  2. Выберите переключатель Когда шаблоны не определены (рекомендуется)
  3. Нажмите на application/json в Content Type.
      {"statusCode": 200}
#set($domainsList = ['test.com','abc.in'])
#foreach( $domain in domainList)
    if(($input.params('origin').startsWith("https") && $input.params('origin').endsWith($domain) || $input.params('origin').endsWith("localhost") || $input.params('origin').endsWith("localhost:8100"))
    #set($context.responseOverride.header.Access-Control-Allow-Origin = $input.params('origin'))
    #break
    #end
#end

В условии If я также указал локальный хост, так как я должен тестировать свои приложения с локального хоста: 8100, а для приложений Android заголовок Origin — https://localhost.

Мы можем использовать компараторы на основе Java в шаблоне Apache Velocity.

-> Ссылки: https://velocity.apache.org/engine/1.7/user-guide.html

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