限制用户对某些功能的操作。唯一标识未登录的用户

问题描述 投票:0回答:1

我正在使用一个api,该API包括发送用于重置密码和确认电子邮件的电子邮件。以及“用户注册”之类的功能。

我正在尝试包括一个动作限制器,该限制器允许用户在给定的时间范围内有限次数地执行这些动作,以防止恶意使用。

起初,我认为使用IP地址就可以了,因为即使是恶意用户,最终也会用尽IP地址(至少该即时消息知道),但后来我意识到,这可能会阻止位于大型建筑物内的用户,并可能给VPN用户带来不便。

唯一标识未签名用户的最佳方法是,以限制其对某些功能的操作?这可能吗? FAANG如何处理此问题?

这是我在nodejs中编写的示例,如果有人对如何使其更具独特性有任何反馈和/或想法,我将不胜枚举。

const db = require('../../common/database');
// const ActionLimiterEnum = require('../../enums/action-limiter').actionLimiterEnum;
const NumberUtil = require('../../utils/number');
const ObjectUtil = require('../../utils/object');


// !==========================================================================================!
// This module has been put on hold until I can think of a way to uniquely identify users
// Major problem about this is that it may deny large groups of people whom use the same ip 
// VPNS and/or large buildings
//
// Could cause more problems than it solves
// !==========================================================================================!



// Simple action limiter for how often a user can perform actions
// Needs to be saved to a database and not an instance because there may be multiple instances and/or they may be reset

// Object of action or "signIn"
async function actionLimiter(action,ip){
  const d = {err: {code:0,message:""},res:{}}; let r,sql,vars;

  r = await checkLimit(action,ip);
  if(r.err.code) return r;

  r = await incrementLimit(action,ip);
  if(r.err.code) return r;

  return d;
}

async function checkLimit(action,ip){
  const d = {err: {code:0,message:""},res:{}}; let r,sql,vars;

  if(action === "signIn"){
    r = await checkLimit(ActionLimiterEnum.signInShortTerm,ip); if(r.err.code) return r;
    r = await checkLimit(ActionLimiterEnum.signInMidTerm,ip); if(r.err.code) return r;
    r = await checkLimit(ActionLimiterEnum.signInLongTerm,ip); if(r.err.code) return r;
    return d;
  }

  const numberIp = NumberUtil.ipToNumber(ip);

  var deleteDate = new Date();
  deleteDate.setMilliseconds(deleteDate.getMilliseconds() - action.time);

  sql = "DELETE FROM m_admin_action_limiter WHERE action_id = ? AND created_date <= ?";
  vars = [action.id,deleteDate];
  r = await db.query(sql,vars);
  if(r.err.code) return r;

  sql = "SELECT * FROM m_admin_action_limiter WHERE action_id = ? AND ip = ?";
  vars = [action.id,numberIp];
  r = await db.query(sql,vars);
  if(r.err.code) return r;

  if(r.res.length){
    const results = ObjectUtil.toCamelCaseKeys(r.res[0]);
    if(results.actionCount >= action.maxCount){
      d.err.code = 1;
      d.err.message = "Sorry this ip has performed this action too often please try again later. ";

      switch(action.id){
        case ActionLimiterEnum.signInShortTerm.id:
        case ActionLimiterEnum.signInMidTerm.id:
        case ActionLimiterEnum.signInLongTerm.id:
          d.err.message += "If you're having trouble remembering your password you can reset it via email. ";
          break;
        default: 
          break;
      }

      d.err.actionLimited = true;
      return d;
    }
  }

  return d;
}

async function incrementLimit(action,ip){
  const d = {err: {code:0,message:""},res:{}}; let r,sql,vars;

  if(action === "signIn"){
    r = await incrementLimit(ActionLimiterEnum.signInShortTerm,ip); if(r.err.code) return r;
    r = await incrementLimit(ActionLimiterEnum.signInMidTerm,ip); if(r.err.code) return r;
    r = await incrementLimit(ActionLimiterEnum.signInLongTerm,ip); if(r.err.code) return r;
    return d;
  }

  const numberIp = NumberUtil.ipToNumber(ip);
  const timenow = new Date();

  sql = "SELECT admin_action_limiter_id FROM m_admin_action_limiter WHERE action_id = ? AND ip = ?";
  vars = [action.id,numberIp];
  r = await db.query(sql,vars);
  if(r.err.code) return r;

  if(r.res.length){
    // update
    const id = r.res[0]['admin_action_limiter_id']

    sql = "UPDATE m_admin_action_limiter SET action_count = action_count + 1 WHERE admin_action_limiter_id = ?";
    vars = [id];
    r = await db.query(sql,vars);
    if(r.err.code) return r;
  }else{
    // insert
    sql = "INSERT INTO m_admin_action_limiter (action_id,ip,action_count,created_date) VALUES(?,?,?,?)";
    vars = [action.id,numberIp,1,timenow];
    r = await db.query(sql,vars);
    if(r.err.code) return r;
  }

  return d;
}

module.exports = {
  actionLimiter, 
  checkLimit,
  incrementLimit,
  Enum: ActionLimiterEnum,
};



//  SQL

// -- -----------------------------------------------------
// -- Table `m_admin_action_limiter`
// -- -----------------------------------------------------
// CREATE TABLE IF NOT EXISTS `m_admin_action_limiter`(
// `admin_action_limiter_id` int(11) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
// `action_id` int(2) unsigned NOT NULL,
// `ip` int(11) unsigned NOT NULL,
// `action_count` unsigned int(11) DEFAULT 1,
// `created_date` DATETIME NOT NULL
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

// ALTER TABLE `m_admin_action_limiter`
//   ADD CONSTRAINT m_admin_action_limiter_unique UNIQUE (`action_id`,`ip`);
// CREATE INDEX `created_date_index` ON `m_admin_action_limiter` (`created_date`);




// Enums


// time: (days * hours * minutes * seconds * milliseconds)
// time - amount of times they can try within the alotted count
// const actionLimiterEnum = {
//   signInShortTerm: {
//     id: 1,
//     time: (1 * 1 * 60 * 60 * 1000), // 1 hour
//     maxCount: 24,
//   },
//   signInMidTerm: {
//     id: 2,
//     time: (7 * 24 * 60 * 60 * 1000), // 7 days
//     maxCount: 150,
//   },
//   signInLongTerm: {
//     id: 3,
//     time: (120 * 24 * 60 * 60 * 1000), // 120 days
//     maxCount: 840,
//   },
//   authToken: {
//     id: 4,
//     time: (1 * 24 * 60 * 60 * 1000), // 1 day
//     maxCount: 16,
//   },
//   createAccount: {
//     id: 5,
//     time: (90 * 24 * 60 * 60 * 1000), // 90 days
//     maxCount: 3,
//   },
//   passwordCheck: {
//     id: 6,
//     time: (7 * 24 * 60 * 60 * 1000), // 1 week
//     maxCount: 150,
//   },
// }

// module.exports = {
//   actionLimiterEnum,
// };
node.js unique limit user-activity
1个回答
0
投票

通知用户,如果未启用Cookie,站点将无法正常运行。当他们进入注册或登录页面(如果不存在)时,创建时间戳cookie。如果用户请求登录或注册,而您的cookie在尝试读取其时间戳时不存在,我们知道他们已禁用cookie或它可能是恶意用户。如果显然存在,则您将比较时间戳并在请求逻辑运行后更新其cookie时间戳。现在,如果不存在,请告诉他们启用Cookie,否则网站将无法正常工作。这样可以防止恶意使用,并排除IP地址。如果恶意用户确实是您的问题/担忧,那么解决IP地址问题的唯一方法就是使用Cookie,或者比您目前尝试识别恶意意图的逻辑要复杂得多(如果采取措施,可能会让您shoot脚反对误报,尽管我不建议使用此路线)。确保您也采取措施保护Cookie。

© www.soinside.com 2019 - 2024. All rights reserved.