javascript - 防止恶意用户滥用和发送未经身份验证的开放 API

标签 javascript api rest security frontend

这是我在构建与 REST API 服务交互的基于 Web 的小型项目时多次遇到的安全问题。例如,假设您正在构建一个基于 JavaScript 的休闲游戏,您想要一个高分排行榜,因此您需要将用户的分数发布到数据库中。
最简单的解决方案是构建一个简单的 Web 服务,例如使用接受 GET 的 PHP、Node.js 或 Python请求并将结果保存到数据库。让我们想象一下 API 看起来像这样:GET https://www.example.com/api/highscore?name=SuperGoat31&score=500创建这样一个用于发布高分的 API 有一些明显的缺点。恶意用户可以编写一段三行 PHP 代码来向数据库发送充满错误结果的垃圾邮件,例如:

for ($i = 0; $i < 100; i++) {
    file_get_contents("https://www.example.com/api/highscore?name=SuperGoat31&score=5000000");
}
所以,我正在寻找一种方法来防止这种情况发生。这主要与小型爱好或黑客马拉松项目有关,它们只需要某种保护来防止最明显的攻击,而不是需要严格安全的大型企业应用程序。我能想到的几件事:
1. 某种形式的认证
解决这个问题的一个明显方法是拥有用户帐户并且只允许来自登录用户的请求。不幸的是,这给需要先获得帐户的用户设置了很大的障碍。它还需要建立一个完整的身份验证工作流程,包括密码恢复和正确加密密码等。
2. 一次性 token 保护
在服务器端生成一个 token 并在首次加载时将其提供给用户,然后只允许提供该特定 token 的请求。很简单,但也很容易通过在浏览器 Web 检查器中查找请求并将其用于三行 PHP 脚本来规避。
3. 记录IP地址,恶意使用时封禁
这可以工作,但我觉得它对隐私不是很友好。此外,记录 IP 地址需要 GDPR欧洲用户的同意。也不会阻止实际的垃圾邮件本身,因此您可以在开始禁止 IP 地址之前先清理垃圾。
4.使用外部服务
有一些服务可以解决这个问题。例如,过去我使用 Google 的 reCAPTCHA 来防止恶意使用。但这也意味着集成外部服务,确保您保持最新,关注隐私方面(尤其是关于 reCAPTCHA 之类的服务)等。对于周末项目来说感觉有点多。
5. 限制请求
我觉得这可能是最简单的解决方案,实际上有点作用。这确实需要某种形式的 IP 地址记录(这可能会导致 3 中所述的问题),但至少您可以在之后很快删除这些 IP 地址。
但我确信还有其他方法我错过了,所以我很想看看解决这个问题的其他方法。

最佳答案

考虑到所有提到的限制,我建议使用多种方法:

  • 基于一次性 token 的简单 session 身份验证
  • 脚本混淆
  • 具有完整性控制的请求加密

  • 例子:
    let req_obj = {
      user: 'SuperGoat31',
      score: 123456,
      sessionId: '4d2NhIgMWDuzarfAY0qT3g8U2ax4HCo7',
    };
    req_obj.hash = someCustomHashFunc(JSON.stringify(req_obj));
    // now, req_obj.hash = "y0UXBY0rYkxMrJJPdoSgypd"
    
    let req_string = "https://www.example.com/api/cmd?name=" +
                     req_obj.user +
                     "&data=" +
                     Buffer.from(JSON.stringify(req_obj)).toString('base64');
    
    // now, your requests will look like that:
    "https://www.example.com/api/cmd?name=SuperGoat31&data=eyJ1c2VyIjoiU3VwZXJHb2F0MzEiLCJzY29yZSI6MTIzNDU2LCJzZXNzaW9uSWQiOiI0ZDJOaElnTVdEdXphcmZBWTBxVDNnOFUyYXg0SENvNyIsImhhc2giOiJ5MFVYQlkwcllreE1ySkpQZG9TZ3lwZCJ9"
    
    对于休闲玩家,这允许非常快速地开始玩,因为不需要显式注册。生成时, token 可能会保存为 cookie 以供重复使用,但这不是必需的,单次使用也足够了。没有收集到个人信息。
    但是,如果可以选择短期存储一些客户端信息,则 token 可能不仅仅是一些随机字节,而是一个加密字符串,包含一些参数,例如随机盐 + IP 地址 + 昵称 + 代理 id + 等。在这种情况下,您可能会在检测到欺诈性客户后默默地忽略某些请求。
    显然,这对于专业人士来说很容易破解,但这不是我们的目标。当这些简单的方法与数千字节的游戏逻辑混合并被混淆时,弄清楚如何处理它需要大量的知识和时间,这可能是一个足够的障碍。
    由于这完全是为了方便和保护之间的平衡,您可以实现一些额外的评分逻辑来检测作弊尝试,例如最终得分不能以“0”结尾,或者不能是偶数等。这将允许您计算作弊尝试(在除了计算伪造的请求),然后估计实现的方法组合的效率。

    关于javascript - 防止恶意用户滥用和发送未经身份验证的开放 API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68860452/

    相关文章:

    postgresql - 如何使用CKAN API按多个标签搜索数据集?

    jquery - 在将图像添加为背景图像之前检查图像是否存在

    java - Spring Batch + Spring API REST

    javascript - 通过传入日期创建 Javascript Date 对象?什么是日期字符串?

    javascript - 如何在 React 中正确捕获 Materialize-CSS 日期选择器值?

    PHP 警报消息

    javascript - 无法将 UTC 转换为 PST,反之亦然

    javascript - 使用 cordova 下载 Youtube 视频

    database - 将 REST API 与 Neo4j 一起使用?

    java - Jasper 服务器报告服务