保护用户注册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”),这个秘密盐需要对应用程序是唯一的,并保密。
注册页面的生成方式类似于:
- 通过连接所有信息来创build一个纯文本string进行签名。 例如,如果过期是1411660627,而MD5哈希用户代理是0f7aee3e0a65ff9440d2a0183b4b1f49,则您的基本签名将类似于:
1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49
。 - 将秘密盐附加到该string:
1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
。 - 散列该string,使用任何散列algorithm(例如MD5)。 结果是你的签名:
0742d84065cb9497c1ba4c1d33190a93
。 - 将您的签名连接到纯文本string以获取您的安全令牌:
1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93
。 这是用户收到并必须提交的内容。
为了validation令牌,然后进行类似的操作。 当服务器收到令牌1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93
,它执行这些步骤:
- 从令牌中提取到期并检查它是否仍然有效。 如果
1411660627
小于当前时间戳,那么它仍然有效。 - 计算用户代理的散列,并检查它是否与令牌上的代码匹配:
0f7aee3e0a65ff9440d2a0183b4b1f49
。 - 像以前一样重新生成签名:
expiration-useragent_secretsalt
使用从用户收到的安全令牌的数据。 在我们的例子中:1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde
。 - 像以前一样计算string的散列。 如果它与令牌(
0742d84065cb9497c1ba4c1d33190a93
)中的第三个参数匹配,则安全令牌有效。
优点:这个解决scheme不需要数据库,但它同样安全(只要盐保密在服务器中)。
缺点:相同的安全令牌可以多次使用,直到过期。
这听起来像是你没有充分利用你的math问题对策 – 你用它作为客户端的障碍,但正如你所观察到的,一个机器人可以跳过客户端,并调用你的API。 为了使它更有效,而不是在客户端上随机生成问题,您可以在服务器上生成问题,将答案保存在会话中( req.session.mathProblemAnswer = 4
),然后用API调用发送用户的答案可以在会话中对照答案进行检查。
在@Qualcuno中使用一个标记来描述他的回答将直接针对垃圾邮件发送你的API端点,但是有足够聪明的机器人来加载你的注册页面,扫描隐藏的字段并提交表单(包括令牌)。 一般来说,使用CSRF保护仍然是一个好主意, Sails已经内置了支持 。
- 针对社交媒体的大型应用的NodeJs服务器端框架
- 以编程方式清除cloudflarecaching
- nodejs https api请求错误错误:在TLSWrap.onread(net.js:568:26)处的exports._errnoException(util.js:1018:11)处读取ECONNRESET
- 为现有NodeJS服务器生成Swagger文档
- Google日历事件更改时更新数据库
- 使用pipe道节点请求阻止交换机api上的504网关超时
- 如何在Snapdeal上生成X-Auth-Token和X-Seller-AuthZ-Token
- 我可以使用服务器端生成的令牌上传文件到谷歌驱动器在客户端(angularjs)
- 通过NodeJS调用远程API,并将结果附加到我的API失败