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

У меня есть массив действительных источников

const whitelist = [ 'a.com', 'b.co.uk' ]

const validOrigin = str => {
    const url = new URL( str )
    return whitelist.includes( url.host )
}

console.log(validOrigin('https://www.a.com'))

Он возвращает false из-за www., я не хочу просто добавлять копию с www. в массив действительных источников. Я хотел бы способ, который покрывает это и все остальное, что неожиданно.

0
Will 19 Янв 2022 в 19:54
Касательно, но это хорошо- известно, что заголовок Origin можно легко подделать, и он (и CORS в более широком смысле) не предназначен для обеспечения какой-либо безопасности в этой области, и на него не следует полагаться при принятии решений, связанных с безопасностью, на любом уровне в ваш стек.
 – 
esqew
19 Янв 2022 в 20:00

3 ответа

Принимая во внимание, что по правилам, www.example.com и example.com различны по происхождению:

Если вы хотите сопоставить любое происхождение в том же домене или поддомене доменов в белом списке, вам необходимо:

  • Скиньте схему и порт - что вы уже делаете
  • Проверьте точное совпадение - что вы уже делаете
  • Проверить совпадение, оканчивающееся на ., за которым следует строка (чтобы остановить сопоставление third-party-hacker-a.com)

Так что-то вроде:

const validOrigin = str => {
    const url = new URL( str )
    const host = url.host;
    return whitelist.some( element => {
        if (element === host) return true;
        return element.endsWith(`.${host}`);
    } )
}
1
Quentin 19 Янв 2022 в 20:04

Вы можете попробовать что-то вроде этого

str = str.replace( new RegExp("((http)(s)?:\/\/)?(www.)?","gm"),"")

Это удалит первую часть URL

-1
Kossay Rhafiri 19 Янв 2022 в 20:02

Функция Array.prototype.includes принимает только значение для поиска и ищет точное совпадение.

Вам нужно будет использовать функцию, которая принимает обратный вызов для проверки элементов, например, функция Array.prototype.findIndex.

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

const whitelist = [ /(^|\.)a\.com$/i, /(^|\.)b\.co\.uk$/i ];

const validOrigin = str => {
    const url = new URL(str);
    const index = whitelist.findIndex(el => el.test(url.host));
    return index !== -1;
};

document.querySelectorAll("#tests > li").forEach(li => {
  const str = li.dataset.value;
  const result = validOrigin(str);
  li.textContent = `${str} = ${result}`;
});
<ul id="tests">
  <li data-value="http://a.com/foo"></li>
  <li data-value="http://www.a.com/foo"></li>
  <li data-value="http://dev.a.com/foo"></li>
  <li data-value="http://banana.com/foo"></li>
  <li data-value="http://a.com.b.ru/foo"></li>
</ul>
-1
Richard Deeming 19 Янв 2022 в 20:10
2
Разве это не допустит ничего, что заканчивается на .com? как банан.com
 – 
Will
19 Янв 2022 в 20:03
Хорошая точка зрения; Я обновил свой ответ.
 – 
Richard Deeming
19 Янв 2022 в 20:10