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, а также исходный домен, которому я доверяю, из списка доверенных доменов.
- В ресурсах шлюза API щелкните любой метод OPTIONS и перейдите к запросу на интеграцию.
- Выберите переключатель Когда шаблоны не определены (рекомендуется)
- Нажмите на 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