Отображение статуса безопасности всех внешних ссылок с использованием Google Safe Browsing Lookup API

Некоторое время назад я искал стратегию защиты своего сайта от внешних ссылок, предоставляемых участниками форума. Я пытаюсь создать собственную базу данных вредоносных URL-адресов. Но это сложнее, чем кажется. Огромное количество ссылок трудно обработать. Поэтому я поискал API-сервис, который мог бы удовлетворить мои требования, и обнаружил Google Safe Browsing API — бесплатный сервис от Google — и попытался добавить его на форум Discourse.

Результат на моём форуме
*при наведении курсора

Вот как это сделать.
Чтобы добавить иконку после всех внешних ссылок в Discourse и отображать всплывающие подсказки с информацией о безопасности ссылок, используя Google Safe Browsing Lookup API (v4), выполните следующие шаги:

  1. Создайте API-ключ для Google Safe Browsing:

    • Перейдите в Google Cloud Console
    • Создайте новый проект или используйте существующий
    • Включите Safe Browsing API
    • Создайте API-ключ для этого проекта
      *Это всё бесплатно.
  2. Войдите в админ-панель Discourse:

    • Войдите в Discourse под учётной записью администратора
  3. Перейдите к настройкам темы:

    • Перейдите в раздел «Admin» → «Customize» → «Themes»
    • Выберите тему, которую хотите редактировать, или создайте новую тему или компонент темы
  4. Добавьте CSS:

    • Нажмите «Edit CSS/HTML» для выбранной темы

    • Во вкладке «CSS» добавьте следующий код:

      a[target="_blank"]:after {
          content: url('https://example.com/icon.png'); /* Замените на URL вашей иконки */
          margin-left: 5px; /* Отступ между ссылкой и иконкой */
          display: inline-block;
      }
      
      .tooltip {
          position: relative;
          display: inline-block;
      }
      
      .tooltip .tooltiptext {
          visibility: hidden;
          width: 200px;
          background-color: #555;
          color: #fff;
          text-align: center;
          border-radius: 6px;
          padding: 5px;
          position: absolute;
          z-index: 1;
          bottom: 125%; /* Позиция всплывающей подсказки */
          left: 50%;
          margin-left: -100px;
          opacity: 0;
          transition: opacity 0.3s;
      }
      
      .tooltip:hover .tooltiptext {
          visibility: visible;
          opacity: 1;
      }
      
  5. Добавьте JavaScript:

    • Во вкладке «Header» темы добавьте следующий код:

      <script type="text/discourse-plugin" version="0.8">
        api.onPageChange(() => {
          const externalLinks = document.querySelectorAll('a[href^="http"]:not([href*="' + window.location.hostname + '"])');
          const apiKey = 'ВАШ_GOOGLE_API_КЛЮЧ'; // Замените на ваш API-ключ
          const lookupUrl = 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=' + apiKey;
      
          externalLinks.forEach(link => {
            link.setAttribute('target', '_blank');
            link.classList.add('tooltip');
      
            const tooltipText = document.createElement('span');
            tooltipText.className = 'tooltiptext';
            tooltipText.innerText = 'Проверка безопасности ссылки...';
            link.appendChild(tooltipText);
      
            fetch(lookupUrl, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                client: {
                  clientId: 'вашакомпания',
                  clientVersion: '1.5.2'
                },
                threatInfo: {
                  threatTypes: ['MALWARE', 'SOCIAL_ENGINEERING'],
                  platformTypes: ['ANY_PLATFORM'],
                  threatEntryTypes: ['URL'],
                  threatEntries: [
                    { url: link.href }
                  ]
                }
              })
            })
            .then(response => response.json())
            .then(data => {
              if (data.matches && data.matches.length > 0) {
                tooltipText.innerText = 'Предупреждение: эта ссылка может быть небезопасной!';
                tooltipText.style.backgroundColor = '#ff0000';
              } else {
                tooltipText.innerText = 'Эта ссылка безопасна.';
              }
            })
            .catch(error => {
              tooltipText.innerText = 'Ошибка при проверке безопасности ссылки.';
            });
          });
        });
      </script>
      

      Этот JavaScript:

      • Находит все внешние ссылки и устанавливает их открытие в новой вкладке
      • Добавляет иконку после ссылки
      • Проверяет ссылку с помощью Google Safe Browsing API и отображает результат во всплывающей подсказке
  6. Сохраните и примените тему:

    • Нажмите «Save», чтобы сохранить изменения
    • Если вы создали новую тему, установите её как тему по умолчанию или назначьте нужным группам пользователей

Эти шаги обеспечат наличие иконки после всех внешних ссылок в вашем экземпляре Discourse, а всплывающие подсказки будут отображать статус безопасности ссылок с использованием Google Safe Browsing API.

Изменение для безопасности
Вам следует добавить свой веб-сайт в раздел ограничений веб-сайтов для использования Google API.

Опция

Использовать иконку Font Awesome

Чтобы использовать иконку из Font Awesome, вот обновлённый CSS:

Обновлённый CSS с иконками Font Awesome

/* Убедитесь, что Font Awesome подключён */
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css');

/* Добавление иконки Font Awesome после внешних ссылок */
a[target="_blank"]:after {
    content: "\f35d"; /* Unicode-код иконки внешней ссылки Font Awesome */
    font-family: 'Font Awesome 5 Free'; /* Семейство шрифтов Font Awesome */
    font-weight: 900; /* Жирное начертание Font Awesome */
    margin-left: 5px; /* Отступ между ссылкой и иконкой */
    display: inline-block;
}

Пояснение:

  1. Импорт Font Awesome:

    • CSS начинается с импорта стилей Font Awesome через CDN.
  2. Добавление иконки:

    • Свойство content в селекторе a[target="_blank"]:after установлено в значение "\f35d", что является Unicode-кодом иконки внешней ссылки Font Awesome.
    • Свойство font-family установлено в ‘Font Awesome 5 Free’, а font-weight — в 900, чтобы использовать жирную версию иконки.

Надеюсь, это будет полезно тем, кто ищет то же самое, что и я.

Это очень крутая идея!!

:warning: Обратите внимание: добавляя свой ключ API Google Cloud в компонент темы, вы делаете его доступным для всех. Если кто-то получит доступ к вашему ключу API, это может привести к огромному счету. :warning:

Либо убедитесь, что ваш ключ API имеет достаточные ограничения (например, он может получать доступ только к API Safe Browsing), либо настройте серверный прокси, чтобы хранить ключ API в безопасности на вашем сервере.

Или… превратите это в плагин и оставьте API-общение происходить на заднем плане, где никто не сможет это увидеть.

Вот что я и хотел сказать :wink:

Что ж, прокси — это особый вид посредника, а также хорошая идея.

Это точно было OR.

Спасибо за отличный совет. :blush: Я полагаю, в консоли Google Cloud есть механизм для блокировки доступа к API; просто добавьте туда свой веб-сайт.

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

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

(Если этот сервис подпадает под ответственность, я не знаю)

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

Рад, что смог привлечь ваше внимание, и благодарю за интерес к созданию этого плагина.

Я надеюсь и рад видеть это в функции тоже.

Знает ли кто-нибудь, работает ли это с самописной версией Discourse? В панели администратора не вижу опции для настройки параметров темы.

В этой теме нет настроек темы — файл настроек пуст:

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

Вы можете создать новый компонент темы и добавить его в свою тему