使用Google Safe Browsing查询API显示所有外部链接的安全状态

不久前,我一直在寻找一种策略来保护我的网站免受论坛成员提供的外部链接的侵害。我试图建立自己的恶意网址数据库。但这比你想象的要困难。链接的数量庞大,难以筛选。因此,我寻找了一个能够满足我需求的 API 服务,并发现了 Google Safe Browsing API,这是 Google 提供的一项免费服务 API,并尝试将其添加到 Discourse 论坛。

我的论坛中的结果
*鼠标悬停时

方法如下。
要在 Discourse 中为所有外部链接添加图标,并显示工具提示以使用 Google Safe Browsing Lookup API (v4) 显示链接的安全状态,请按照以下步骤操作:

  1. 创建 Google Safe Browsing API 密钥

    • 转到 Google Cloud Console
    • 创建一个新项目或使用现有项目
    • 启用 Safe Browsing API
    • 为该项目创建 API 密钥
      *一切都是免费的。
  2. 登录 Discourse 管理员

    • 使用您的管理员帐户登录 Discourse
  3. 访问主题自定义

    • 转到“管理”->“自定义”->“主题”
    • 选择要编辑的主题,或创建一个新主题或主题组件
  4. 添加 CSS

    • 点击所需主题的“编辑 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 = 'YOUR_GOOGLE_API_KEY'; // 替换为您的 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 = 'Checking link safety...';
            link.appendChild(tooltipText);
      
            fetch(lookupUrl, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json'
              },
              body: JSON.stringify({
                client: {
                  clientId: 'yourcompany',
                  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 = 'Warning: This link may be unsafe!';
                tooltipText.style.backgroundColor = '#ff0000';
              } else {
                tooltipText.innerText = 'This link is safe.';
              }
            })
            .catch(error => {
              tooltipText.innerText = 'Error checking link safety.';
            });
          });
        });
      </script>
      

      此 JavaScript 将:

      • 查找所有外部链接并将其设置为在新标签页中打开
      • 在链接后添加一个图标
      • 使用 Google Safe Browsing API 检查链接并在工具提示中显示结果
  6. 保存并应用主题

    • 点击“保存”以保存您的更改
    • 如果您创建了一个新主题,请将其设置为默认主题或分配给所需的用户组

这些步骤将确保您的 Discourse 实例中的所有外部链接都将在其后显示一个图标,并且工具提示将使用 Google Safe Browsing API 显示链接的安全状态。

安全编辑
您应该将您的网站添加到 Google API 使用量的网站限制部分。

选项

使用 Font Awesome 图标

要使用 Font Awesome 的图标。这是更新后的 CSS:

使用 Font Awesome 图标的更新 CSS

/* 确保已包含 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"; /* Font Awesome 外部链接图标的 Unicode */
    font-family: 'Font Awesome 5 Free'; /* Font Awesome 字体系列 */
    font-weight: 900; /* Font Awesome 实心权重 */
    margin-left: 5px; /* 链接和图标之间的间距 */
    display: inline-block;
}

说明:

  1. Font Awesome 导入

    • CSS 首先从 CDN 导入 Font Awesome CSS。
  2. 图标添加

    • a[target="_blank"]:after 选择器中的 content 属性设置为 "\f35d",这是 Font Awesome 外部链接图标的 Unicode。
    • font-family 设置为 ‘Font Awesome 5 Free’,font-weight 设置为 900,以使用图标的实心版本。

希望这对和我一样寻找相同东西的人有所帮助。

3 个赞

这个主意太棒了!!

:warning: 请注意,将您的 Google Cloud API 密钥包含在主题组件中会将其暴露给全世界。当人们可以访问您的 API 密钥时,他们可能会给您带来巨额账单。:warning:
您应该确保您的 API 密钥已获得充分的范围限制(例如,它只能访问 Safe Browsing API),或者您应该添加一个服务器端代理,以便您可以将 API 密钥安全地保存在您的服务器上。

3 个赞

或者……将其变成一个插件,并在后台保持 API 对话,这样没有人可以看到。

1 个赞

我就是这个意思 :wink:

2 个赞

代理是一种特殊的中间人,也是一个好主意。

这绝对是一个 OR。

1 个赞

感谢您的宝贵建议。 :blush: 我相信 Google Cloud Console 中有一个阻止 API 访问的机制;请在此处添加您的网站。

因为我缺乏编写插件的必要技能。我认为这个策略是基础和直接的。但是,如果有愿意创建的人,我认为这比我的方式要好。我将非常激动。

1 个赞

与此同时,我甚至建议这可能值得一个功能请求。

(如果该服务有责任,那我就不知道了)

3 个赞

我不能做任何承诺,但在接下来的几个月里,当我有一些空闲时间时,我一定会考虑这一点。

2 个赞

很高兴引起了您的注意,也很感谢您对制作此插件表现出的兴趣。

我希望并很高兴也能在功能中看到这一点。

有人知道这是否适用于 Discourse 的自托管版本吗?在管理员中似乎没有“自定义”主题设置的选项。

该主题没有主题设置,设置文件为空:

此外,为了更改从 GitHub 下载的主题,您需要分叉(fork)它,编辑您的分叉,然后使用您的分叉。

2 个赞

您可以创建一个新的主题组件并将其添加到您的主题中

2 个赞