关于angularjs:隐藏API URL并防止蛮力攻击

Hiding API URLs and Prevent Brute Force Attacks

我刚刚在节点中构建了一个API。

我正在我的angular应用程序中调用此API来执行登录和注册之类的基础操作,例如:

1
2
3
4
5
6
self.register = function(username, password) {
  return $http.post(API + '/auth/register', {
      username: username,
      password: password
    })
}

所以我的问题是,任何人都可以看到该API URL,那么阻止他们进行"猛烈抨击"以在那里创建用户的原因是什么。 (注意API在我的JS文件中是一个常量)。
登录也是如此,这是什么阻止了某人尝试尝试数百万个用户名和密码组合的暴力行为。

您对此有何建议?

谢谢。


您可以使用一些DDoS保护,例如将nginx代理放在nodejs API的前面,并使用例如limit_req模块:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

对于暴力破解,您可以实施一些锁定逻辑,即在发生大量错误后将阻塞一段时间,例如15-30分钟甚至需要执行管理员操作。

对于需要登录的API,可以使用令牌保护。令牌应在调用身份验证API时发出,并作为响应通过仅HTTP安全cookie进行设置。然后,您可以在API请求标头中传递此令牌,并且在nodejs中每次执行受保护的API执行之前,只需检查它是否有效就可以了,否则请拒绝调用。


您正在询问有关滥用注册和登录保护的问题,基本上是:

  • 如何减轻帐户创建自动化的负担?
  • 如何减轻用户/密码猜测?
  • 非常感谢,这些都是已解决的问题。

    为避免注册"重击",您需要中断自动化。这可以通过从松散到严格的各种方法来实现:

  • 如果仅打算让特定的应用程序/浏览器访问该API,则可以过滤掉所有其他访问者
  • 通过会话/ IP进行限速注册
  • 需要通过验证码
  • 验证电子邮件地址
  • 要求提供私人敏感细节作为身份证明(例如,电话号码,信用卡)
  • 这样做的好处是1-3是可以轻松卸载到现代Web应用程序防火墙的任务,而无需任何其他服务器端编码或额外负载。

    对于"登录保护",除了上述方法1-3外,还建议使用另外两种方法:

  • 双重身份验证(2FA)-这基本上意味着,除了"常规"密码外,用户还需要输入另一个身份验证令牌。该令牌可以由TOTP生成(请参阅Google Authenticator),也可以由服务器通过短信,电子邮件,电话等发送的代码生成。

  • API密钥-这被认为比较安全,因为API密钥通常是很长的唯一字符串,具有很好的熵(与用户/传递组合相比)。有关API密钥的更多信息,请参见。

  • 在我开始之前,我只想简单说一句:我以前看到过一些有关DDoS的评论,我对此压力还不够–您无法自己减轻DDOS。但这是不同的线程。

    祝你好运!


    在Scareddragon上为1。

    如果您生活在云中,那么可以使用nginx作为基于云的更好替代方案-使用云WAF(Web应用程序防火墙)作为DDoS缓解层。例如,查看Incapsula和CloudFlare。

    如果DDoS对您来说是一个严重的问题,而您愿意为此付出代价,那么我绝对会把这留给专家们解决。


    最好通过IP限制反向代理,负载均衡器或任何其他入口点的速率。

    如果您希望在nodejs中执行此操作,则建议使用rate-limiter-flexible

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    const { RateLimiterRedis } = require('rate-limiter-flexible');
    const Redis = require('ioredis');

    const redisClient = new Redis({
      options: {
        enableOfflineQueue: false
      }
    });

    const opts = {
      redis: redisClient,
      points: 5, // 5 points
      duration: 15 * 60, // Per 15 minutes
      blockDuration: 15 * 60, // block for 15 minutes if more than points consumed
    };

    const rateLimiter = new RateLimiterRedis(opts);

    self.register = async function(username, password) {
      let blocked = false;
      try {
        await rateLimiter.consume(clientIP, 1);
      } catch() {
        blocked = true;
      }

      if (blocked) {
        return false;
      }

      return $http.post(API + '/auth/register', {
          username: username,
          password: password
        })
    }