保护用户注册API

我目前正在编写一个带有Sails.js(节点框架)后端的HTML5 Web应用程序。 目前,我的大部分API都是通过PassportJS使用的用户身份validation系统进行保护的。 未经授权的用户试图使用我的API将得到一个401错误。

但是,系统中有一个洞,就是注册API本身。 我显然无法通过用户身份validation来保护我的注册API(因为用户还没有帐户可以login),因此任何人都可以使用许多伪造的帐户轻松地发送垃圾邮件。 在我的注册页面上,我有一个“2 + 2是什么”的小validation问题。 (它是随机生成的),并在客户端进行检查,如果答案正确,则客户端向我的注册API路由发送一个请求,其中包含名称,生日和用户名等所有必要参数。 我怎样才能保证这个API,以确保人们必须通过我的注册页面,不能简单地绕过这个安全措施,直接调用API?

就像注意,我的API不是RESTFul。

有多种可能的方法。

首先,你可以考虑给IP地址添加一个速率限制。 这不是100%有效,但肯定会减慢一些垃圾邮件的尝试。 例如,您可以将每个5分钟由同一个IP地址创build的帐户数量限制为5个。

其次,如果您想使用某种validation码,请考虑reCAPTCHA 。 在不同的validation码服务中,这对于机器人特别有效,因为它们特别使用了OCR识别失败的单词。

最终,为了确保人们在调用API之前实际访问您的注册页面,您可以使用“安全令牌”。 这与用于防止CSRF(跨站请求伪造)攻击的技术是相同的。
当服务器生成注册页面时,它也会将包含唯一生成值的隐藏字段(例如“标记”)传递给客户端。 当客户端请求创build用户时,客户端会将此值和表单一起提交给API服务器,服务器使用该令牌来validation请求。

基本上有两种方法来生成这些令牌。

第一种方法

注册页面创build一个随机的string/数字,并将其存储在数据库中以用作标记。 当用户提交表单时,服务器在数据库中search该标记:如果存在,则提交有效; 否则失败。 令牌然后从数据库中删除。
通过在数据库中存储到期date和客户端的用户代理(与IP不同,用户代理在同一会话期间不太可能改变),可以获得额外的安全性。

优点:每个令牌只能使用一次。
缺点:应用程序需要一个数据库,只需要插入,validation和删除令牌(需要时间和加载数据库)3次。 您还应该从数据库中定期清除过期的令牌。

第二种方法

注册页面通过对包含所有validation信息的纯文本string进行数字签名来创build令牌。 例如,假设您要创build一个在1411660627(UNIX时间戳)上过期并且与用户代理“Mozilla / 5.0 …”关联的令牌。 服务器还拥有一个秘密的盐(例如“123456abcde”),这个秘密盐需要对应用程序是唯一的,并保密。
注册页面的生成方式类似于:

  1. 通过连接所有信息来创build一个纯文本string进行签名。 例如,如果过期是1411660627,而MD5哈希用户代理是0f7aee3e0a65ff9440d2a0183b4b1f49,则您的基本签名将类似于: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49
  2. 将秘密盐附加到该string: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
  3. 散列该string,使用任何散列algorithm(例如MD5)。 结果是你的签名: 0742d84065cb9497c1ba4c1d33190a93
  4. 将您的签名连接到纯文本string以获取您的安全令牌: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93 。 这是用户收到并必须提交的内容。

为了validation令牌,然后进行类似的操作。 当服务器收到令牌1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93 ,它执行这些步骤:

  1. 从令牌中提取到期并检查它是否仍然有效。 如果1411660627小于当前时间戳,那么它仍然有效。
  2. 计算用户代理的散列,并检查它是否与令牌上的代码匹配: 0f7aee3e0a65ff9440d2a0183b4b1f49
  3. 像以前一样重新生成签名: expiration-useragent_secretsalt使用从用户收到的安全令牌的数据。 在我们的例子中: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
  4. 像以前一样计算string的散列。 如果它与令牌( 0742d84065cb9497c1ba4c1d33190a93 )中的第三个参数匹配,则安全令牌有效。

优点:这个解决scheme不需要数据库,但它同样安全(只要盐保密在服务器中)。
缺点:相同的安全令牌可以多次使用,直到过期。

这听起来像是你没有充分利用你的math问题对策 – 你用它作为客户端的障碍,但正如你所观察到的,一个机器人可以跳过客户端,并调用你的API。 为了使它更有效,而不是在客户端上随机生成问题,您可以在服务器上生成问题,将答案保存在会话中( req.session.mathProblemAnswer = 4 ),然后用API调用发送用户的答案可以在会话中对照答案进行检查。

在@Qualcuno中使用一个标记来描述他的回答将直接针对垃圾邮件发送你的API端点,但是有足够聪明的机器人来加载你的注册页面,扫描隐藏的字段并提交表单(包括令牌)。 一般来说,使用CSRF保护仍然是一个好主意, Sails已经内置了支持 。