我目前正在编写一个带有Sails.js(节点框架)后端的HTML5 Web应用程序。现在,我的大部分API都是针对我使用PassportJS的用户身份验证系统提供的。尝试使用我的API的未经授权的用户将收到401错误。
然而,系统中有一个漏洞,即注册API本身。我显然无法使用用户身份验证来保护我的注册API(因为用户还没有帐户可以登录),因此任何人都可以轻松地使用许多虚假帐户向API发送垃圾邮件。在我的注册页面上,我在"什么是2 + 2?"的行中有一个小的验证问题。 (它是随机生成的)并在客户端上进行检查,如果答案是正确的,客户端会向我的注册API路径发送一个请求,其中包含所有必要的参数,如姓名,生日和用户名。如何保护此API以确保用户必须通过我的注册页面,并且不能简单地绕过此安全措施并直接调用API?
正如我所说,我的API不是RESTFul。
答案 0 :(得分:1)
有多种可能的方法。
首先,您可以考虑为IP地址添加速率限制。这不是100%有效,但肯定会减慢一些垃圾邮件的尝试。例如,您可以将每个5分钟将同一IP地址创建的帐户数限制为5个。
其次,如果您想使用某种验证码,请考虑reCAPTCHA。在不同的验证码服务中,这对机器人特别有效,因为它们特别使用无法识别OCR的单词。
最终,为了确保人们在调用API之前实际访问您的注册页面,您可以使用“安全令牌”。这与用于防止CSRF(跨站点请求伪造)攻击的技术相同 当服务器生成注册页面时,它还会向客户端传递包含唯一生成的值的隐藏字段(例如“token”)。当客户端请求创建用户时,客户端会将此值与表单一起提交回API服务器,服务器将使用该令牌验证请求。
基本上有两种生成这些令牌的方法。
第一种方法
注册页面创建一个随机字符串/数字并将其存储在数据库中以用作令牌。当用户提交表单时,服务器会将该令牌搜索到数据库中:如果存在,则提交有效;否则就失败了。然后从数据库中删除令牌 通过在数据库中存储到期日期和客户端的用户代理(与IP不同,用户代理在同一会话期间不太可能更改),可以获得额外的安全性。
优点:每个令牌只能使用一次 缺点:应用程序需要一个数据库,它将被查询3次,仅用于令牌插入,验证和删除(需要时间并向数据库添加负载)。您还应该从数据库中定期清除过期的令牌。
第二种方法
注册页面通过对包含所有验证信息的纯文本字符串进行数字签名来创建令牌。例如,假设您要创建一个在1411660627(UNIX时间戳)上过期的令牌,并且它与用户代理“Mozilla / 5.0 ...”相关联。服务器还拥有一个秘密盐(例如“123456abcde”),它需要对应用程序是唯一的并保密。
注册页面以类似于:
1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49
。1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
。0742d84065cb9497c1ba4c1d33190a93
。1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93
。这是用户收到的内容,必须提交回来。要验证令牌,则完成类似的操作。当服务器收到令牌1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93
时,它会执行以下步骤:
1411660627
小于当前时间戳,则它仍然有效。0f7aee3e0a65ff9440d2a0183b4b1f49
。expiration-useragent_secretsalt
。在我们的示例中:1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
。0742d84065cb9497c1ba4c1d33190a93
)中的第三个参数匹配,则安全令牌有效。优点:此解决方案不需要数据库,但它同样安全(只要盐在服务器中保密)。
缺点:相同的安全令牌可以使用多次,直到它过期。
答案 1 :(得分:1)
听起来你并没有充分利用你的数学问题对策 - 你将它作为客户端障碍使用它,但正如你所观察到的,机器人可以跳过客户端并调用您的API。为了使其更有效,而不是在客户端上随机生成问题,您将在服务器上生成它,在会话中保存答案(req.session.mathProblemAnswer = 4
然后使用API调用发送用户的答案,以便可以根据会话中的答案进行检查。
使用令牌作为@Qualcuno在他的回答中描述将有效对抗直接向您的API端点发送垃圾邮件的机器人,但有些机器人足够智能加载您的注册页面,扫描隐藏字段并提交表单(包括令牌) )。尽管通常使用CSRF保护仍然是个好主意,Sails has built-in support for。