Hus*_*sky 5 javascript security api rest frontend
这是我在构建与 REST API 服务交互的基于 Web 的小型项目时多次遇到的安全问题。例如,假设您正在构建一个基于 JavaScript 的休闲游戏,您想要一个高分排行榜,因此您需要将用户的分数发布到数据库中。
最简单的解决方案是构建一个简单的 Web 服务,例如使用 PHP、Node.js 或 Python,接受GET请求并将结果保存到数据库。让我们想象一下 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");
}
Run Code Online (Sandbox Code Playgroud)
所以,我正在寻找一种方法来防止这种情况发生。这主要涉及小型爱好或黑客马拉松项目,这些项目只需要某种保护来防止最明显的攻击,而不是需要严格安全性的大型企业应用程序。我能想到的有几件事:
1.某种形式的身份验证
解决此问题的一个明显方法是拥有用户帐户并仅允许来自登录用户的请求。不幸的是,这给需要先获得帐户的用户设置了很大的障碍。它还需要构建一个完整的身份验证工作流程,包括密码恢复和正确加密密码等。
2. 基于一次性令牌的保护
在服务器端生成令牌并在首次加载时将其提供给用户,然后仅允许提供该特定令牌的请求。足够简单,但也很容易通过在浏览器 Web 检查器中查找请求并将其用于三行 PHP 脚本来规避。
3. 记录IP地址并在恶意使用发生时禁止
这可能可行,但我觉得这对隐私不太友好。此外,记录 IP 地址需要欧洲用户的GDPR同意。也不能阻止实际的垃圾邮件发送本身,因此您可能需要先清理混乱,然后再开始禁止 IP 地址。
4. 使用外部服务
有一些服务可以解决此问题。例如,过去我使用 Google 的 reCAPTCHA 来防止恶意使用。但这也意味着集成外部服务,确保其保持最新状态,关注隐私方面(尤其是像 reCAPTCHA 这样的服务)等。对于周末项目来说,这感觉有点太多了。
5. 限制请求
我觉得这可能是最简单、实际可行的解决方案。这确实需要某种形式的 IP 地址记录(这可能会导致 3 中所述的问题),但至少您可以在之后很快删除这些 IP 地址。
但我确信我还错过了其他方法,所以我很想知道解决这个问题的其他方法。
考虑到所有提到的限制,我建议使用多种方法的组合:
例子:
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"
Run Code Online (Sandbox Code Playgroud)
对于休闲玩家来说,这可以非常快速地开始游戏,因为不需要明确注册。生成后,token可能会保存为cookie以供重复使用,但这不是必需的,一次性使用也可以。没有收集个人信息。
但是,如果可以选择短期存储某些客户端信息,则令牌可能不仅仅是一些随机字节,而是一个加密字符串,其中包含一些参数,例如随机盐 + IP 地址 + 昵称 + 代理 ID + 等。在这种情况下,您可能会在检测到欺诈性客户后开始默默地忽略某些请求。
显然,这对于专业人士来说很容易破解,但这不是我们的目标。当如此简单的方法与几千字节的游戏逻辑混合在一起并被混淆时,弄清楚如何处理它需要大量的知识和时间,这可能会成为一个足够的障碍。
由于这一切都是为了方便和保护之间的平衡,您可以实现一些额外的评分逻辑来检测作弊尝试,例如最终分数不能以“0”结尾,或者不能为偶数等。这将允许您计算作弊尝试(在除了计算伪造的请求之外),然后估计所实施的方法组合的效率。
您的解决方案列表主要是缓解措施,如果它们是您唯一的工具,那么它们是好主意。该列表似乎非常详尽。
实际解决这个问题的两种主要方法是:
对于您的具体情况,这两种策略可能都不可能,但如果您不能采用这些策略中的任何一种,您就会陷入不完美的检测机制。