You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Firebase邮箱密码认证设置登录尝试速率限制?

Firebase邮箱密码认证:限制登录尝试次数防范暴力攻击

Firebase Auth本身没有提供可直接配置的登录失败次数限制与延迟功能,但可以通过Cloud Functions + Firestore自定义实现符合你需求的速率限制逻辑,具体方案如下:

核心思路

通过Firestore记录每个用户的登录失败次数与锁定截止时间,在登录请求执行前检查锁定状态,登录失败时更新计数并触发锁定(支持指数增长的超时时间),登录成功时重置计数。

实现步骤

1. 存储登录尝试记录

在Firestore中创建loginAttempts集合,每个文档以用户邮箱(或哈希后的邮箱)为ID,包含以下字段:

  • failedAttempts: 连续登录失败次数(初始为0)
  • lockUntil: 锁定截止时间戳(初始为0,即无锁定)

2. 封装带速率限制的登录云函数

使用Cloud Functions的Callable Function封装登录逻辑,确保所有登录请求都经过验证:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

exports.loginWithRateLimit = functions.https.onCall(async (data, context) => {
  const { email, password } = data;
  const loginAttemptRef = admin.firestore().collection("loginAttempts").doc(email);
  const doc = await loginAttemptRef.get();

  // 检查是否处于锁定状态
  if (doc.exists) {
    const { lockUntil } = doc.data();
    if (Date.now() < lockUntil) {
      const remainingMinutes = Math.ceil((lockUntil - Date.now()) / 60000);
      throw new functions.https.HttpsError(
        "permission-denied",
        `登录失败次数过多,请${remainingMinutes}分钟后再试`
      );
    }
  }

  try {
    // 执行登录验证
    const userCredential = await admin.auth().signInWithEmailAndPassword(email, password);
    // 登录成功,重置失败记录
    await loginAttemptRef.set({ failedAttempts: 0, lockUntil: 0 });
    return { success: true, uid: userCredential.user.uid };
  } catch (error) {
    // 登录失败,更新失败次数与锁定状态
    let failedAttempts = 1;
    let lockUntil = 0;
    const baseLockTime = 10 * 60 * 1000; // 基础锁定时长:10分钟

    if (doc.exists) {
      failedAttempts = doc.data().failedAttempts + 1;
      // 每5次失败,锁定时间指数增长(10分钟 → 20分钟 → 40分钟...)
      if (failedAttempts % 5 === 0) {
        const multiplier = Math.pow(2, Math.floor(failedAttempts / 5) - 1);
        lockUntil = Date.now() + baseLockTime * multiplier;
      }
    }

    await loginAttemptRef.set({ failedAttempts, lockUntil });
    throw new functions.https.HttpsError("invalid-argument", error.message);
  }
});

3. 客户端调用云函数登录

在客户端替换原生的signInWithEmailAndPassword,改为调用上述云函数:

const loginWithRateLimit = firebase.functions().httpsCallable('loginWithRateLimit');

async function submitLogin(email, password) {
  try {
    const result = await loginWithRateLimit({ email, password });
    // 处理登录成功逻辑(如跳转主页)
    console.log('登录成功,用户UID:', result.data.uid);
  } catch (error) {
    // 提示用户错误信息
    alert(error.message);
  }
}

4. 配置Firestore安全规则

防止客户端篡改登录尝试记录,仅允许云函数访问loginAttempts集合:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /loginAttempts/{email} {
      allow read, write: if request.auth.token.firebase.sign_in_provider == "service_account";
    }
  }
}

额外优化建议

  • 邮箱哈希处理:将邮箱进行SHA-256哈希后作为文档ID,避免直接暴露用户邮箱。
  • 定期清理数据:使用Cloud Functions定时任务,删除lockUntil小于当前时间的过期记录,节省存储空间。
  • 锁定提示优化:在客户端显示剩余锁定时间,提升用户体验。

内容的提问来源于stack exchange,提问作者Rusty Miller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:52:55