PHP 怎么检测账号异常

wen PHP项目 4

本文目录导读:

PHP 怎么检测账号异常

  1. 基础行为检测(登录层面)
  2. 用户设备设备指纹检测(中级)
  3. 风险规则引擎(高级)
  4. 实时行为监测(高级)
  5. 综合实践代码
  6. 关键优化建议
  7. 部署注意事项

在 PHP 中检测账号异常,通常需要结合多种技术手段进行综合判断,这里整理了一套从基础到高级的完整检测方案,你可以根据业务需求选择适合的层级。


基础行为检测(登录层面)

这是最常用,也是最先应该做的检测。

登录失败次数限制

// 最简单的防暴力破解
public function checkLoginAttempts($username, $ip) 
{
    $key = 'login_attempts_' . md5($username . $ip);
    $count = Redis::get($key);
    // 15分钟内连续失败5次
    if ($count >= 5) {
        // 锁定账号
        Redis::expire($key, 900);
        throw new \Exception('账号已锁定,请15分钟后再试');
    }
    // 记录失败次数
    Redis::incr($key);
    Redis::expire($key, 900);
}

代理/IP安全检查

public function checkIpRisk($ip) 
{
    $riskList = ['代理IP库', 'VPN', 'TOR节点'];
    if (in_array($ip, $this->getBlackListIPs())) {
        throw new \Exception('IP地址存在风险');
    }
    // 如果是海外IP,要求二次验证
    if ($this->isOverseasIP($ip)) {
        // 触发短信/邮件验证码
    }
}

用户设备设备指纹检测(中级)

设备指纹对比

public function checkDeviceConsistency($userId, $deviceFingerprint) 
{
    $userHistory = UserDevice::where('user_id', $userId)
        ->orderBy('last_login_at', 'desc')
        ->get();
    // 首次设备登录
    if ($userHistory->count() === 0) {
        // 标记为"新设备",要求额外验证
        return ['status' => 'new_device', 'requires_verification' => true];
    }
    // 历史设备登录
    $isKnown = $userHistory->contains($deviceFingerprint);
    if (!$isKnown) {
        // 新设备+异地IP =高风险
        return ['status' => 'suspicious', 'risk_level' => 'high'];
    }
    return ['status' => 'normal'];
}

异地登录检测

public function checkLocationAnomaly($userId, $currentLocation) 
{
    // 获取常用登录地(最近30天)
    $commonLocations = LoginLog::where('user_id', $userId)
        ->where('login_at', '>', now()->subDays(30))
        ->distinct('city')
        ->pluck('city');
    //判断当前登录地是否在常用列表
    if (!$commonLocations->contains($currentLocation['city'])) {
        return 'unusual_location';
    }
   // 地理位置跳跃检测
    $lastLogin = LoginLog::where('user_id', $userId)
        ->latest()
        ->first();
    if ($lastLogin) {
        $distance = $this->calculateDistance(
            $lastLogin->latitude, $lastLogin->longitude,
            $currentLocation['latitude'], $currentLocation['longitude']
        );
        // 4小时内跨越超过1000km很可疑
        $hoursBetween = now()->diffInHours($lastLogin->login_at);
        if ($hoursBetween < 4 && $distance > 1000) {
            return 'impossible_travel';
        }
    }
}

风险规则引擎(高级)

实时风险评分

class RiskEngine 
{
    public function assessRisk($context) 
    {
        $riskScore = 0;
        // 设备异常 +30分
        if ($context['is_new_device']) {
            $riskScore += 30;
        }
        // 地理位置异常 +30分
        if ($context['location_anomaly']) {
            $riskScore += 30;
        }
        // 非常用浏览器 +20分
        if (!$context['is_common_browser']) {
            $riskScore += 20;
        }
        // 非常用操作系统 +20分
        if (!$context['is_common_os']) {
            $riskScore += 20;
        }
        // 浏览器指纹不完整 +10分
        if ($context['incomplete_fingerprint']) {
            $riskScore += 10;
        }
        // 判断风险等级
        if ($riskScore >= 70) {
            return 'high_risk_locked';
        } elseif ($riskScore >= 40) {
            return 'medium_risk_challenge';
        }
        return 'low_risk_normal';
    }
}

实时行为监测(高级)

异常操作模式监测

public function detectBehaviorAnomaly($userId) 
{
    // 1. 点击/操作频率异常(短时间内大量操作)
    $actionsPerMinute = ActionLog::where('user_id', $userId)
        ->where('created_at', '>', now()->subMinutes(1))
        ->count();
    if ($actionsPerMinute > 50) {
        return 'bots_behavior_detected';
    }
    // 2. 页面停留时间异常(0.1秒打开10个页面 = bot)
    $pageViewTime = PageLog::where('user_id', $userId)
        ->avg('time_spent');
    if ($pageViewTime < 0.5) {
        return 'automated_script_usage';
    }
    // 3. 非工作时间大量操作(凌晨3点高频操作)
    $isNight = now()->hour >= 1 && now()->hour <= 5;
    if ($isNight && $actionsPerMinute > 20) {
        return 'timing_anomaly';
    }
    return 'normal_behavior';
}

多因素交叉验证

public function multiFactorVerification($userId, $requestData) 
{
    $verificationFactors = [];
    // 验证邮箱验证码
    $emailCheck = EmailVerification::where('user_id', $userId)
        ->where('code', $requestData['email_code'])
        ->where('expires_at', '>', now())
        ->exists();
    $verificationFactors['email'] = $emailCheck;
    // 验证手机号
    $phoneCheck = SmsVerification::where('user_id', $userId)
        ->where('code', $requestData['phone_code'])
        ->where('expires_at', '>', now())
        ->exists();
    $verificationFactors['phone'] = $phoneCheck;
    // 验证安全令牌(如果绑定)
    $tokenCheck = UserSecurityToken::where('user_id', $userId)
        ->where('token', $requestData['security_token'])
        ->exists();
    $verificationFactors['security_token'] = $tokenCheck;
    // 至少通过2个因素才能解封
    $passed = collect($verificationFactors)->filter(function($value) {
        return $value === true;
    })->count() >= 2;
    return $passed ? 'verified' : 'unverified';
}

综合实践代码

这是一个整合的账号异常检测服务

<?php
class AccountGuardService 
{
    private $redis;
    private $blacklistService;
    public function __construct() 
    {
        $this->redis = Redis::connection();
        $this->blacklistService = new BlacklistService();
    }
    /**
     * 综合检测入口
     */
    public function verifyAccountAccess($userId, $loginContext) 
    {
        $detectResults = [];
        // 1. 黑名单检测
        if ($this->blacklistService->isBlacklisted($loginContext['ip'])) {
            $detectResults['response'] = 'blocked';
            $detectResults['message'] = '您的IP地址在安全黑名单中,请联系客服';
            return $detectResults;
        }
        // 2. 登录失败次数
        $failedAttempts = $this->loginAttempts($userId, $loginContext['ip']);
        if ($failedAttempts >= 5) {
            $detectResults['response'] = 'blocked';
            $detectResults['message'] = '登录失败次数过多,账号已被临时锁定';
            return $detectResults;
        }
        // 3. 设备指纹检查
        $deviceResult = $this->checkDeviceFull($userId, $loginContext);
        // 4. 位置检测
        $locationResult = $this->checkLocationFull($userId, $loginContext);
        // 5. 行为模式检测
        $behaviorResult = $this->checkBehaviorPattern($userId);
        // 6. 综合风险评估
        $riskScore = $this->calculateScore([
            'device' => $deviceResult,
            'location' => $locationResult,
            'behavior' => $behaviorResult,
            'time' => $this->checkLoginTime()
        ]);
        // 根据风险评分决定是否验证
        if ($riskScore >= 80) {
            $detectResults['response'] = 'blocked';
            $detectResults['message'] = '检测到高安全风险操作,账号已被保护锁定';
        } elseif ($riskScore >= 50) {
            $detectResults['response'] = 'verification_required';
            $detectResults['message'] = '检测到异常登录,需完成多因素验证';
            // 强制二次验证
            $this->sendVerificationCodes($userId);
        } else {
            $detectResults['response'] = 'normal';
            $detectResults['message'] = '登录环境正常';
        }
        // 记录审计日志
        $this->logSecurityEvent($userId, $loginContext, $detectResults);
        return $detectResults;
    }
    // ... 以上各方法的具体实现
}

关键优化建议

优化项 说明
数据持久化 异常检测结果应保存到数据库,方便追溯
告警机制 高风险触发时通知管理员(邮件/短信)
机器学习 用历史数据训练模型,提高检测准确率
人工介入 对于中风险的场景,支持管理员后台手动审核
响应层级 不同风险等级采取不同措施(提示、验证码、锁定、冻结)
避免误报 设置阈值时,加入用户历史行为画像作为参考

部署注意事项

  1. 性能优化:使用 Redis 存储频繁变更的检测数据,避免频繁读写数据库
  2. 隐私合规:设备指纹需符合GDPR等数据隐私法规
  3. 用户体验:过于严格的检测会导致正常用户流失,需要设置合理的阈值
  4. 降级策略:当检测服务不可用时,应放行并记录日志,而不是阻止所有访问

这套方案从多维度构建了账号异常检测体系,你可以根据实际需求选择实施,如果还需要更深入的实现细节(如设备指纹生成代码、地理位置计算逻辑等),可以继续探讨。

抱歉,评论功能暂时关闭!