本文目录导读:

我来为您设计一个PHP项目异常登录检测提醒系统,这个系统可以检测和提醒用户异常登录行为,提高账户安全性。
数据库设计
-- 用户登录日志表
CREATE TABLE user_login_logs (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
login_time DATETIME NOT NULL,
ip_address VARCHAR(45) NOT NULL,
user_agent TEXT,
login_status ENUM('success', 'failed', 'suspicious') DEFAULT 'success',
location VARCHAR(255),
risk_score DECIMAL(3,2) DEFAULT 0.00,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_login_time (login_time),
INDEX idx_ip_address (ip_address)
);
-- 用户安全设置表
CREATE TABLE user_security_settings (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL UNIQUE,
trusted_devices JSON,
trusted_locations JSON,
login_notification BOOLEAN DEFAULT TRUE,
suspicious_login_alert BOOLEAN DEFAULT TRUE,
max_failed_attempts INT DEFAULT 5,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 异常登录警报表
CREATE TABLE login_alerts (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
alert_type VARCHAR(50) NOT NULL,
alert_message TEXT,
ip_address VARCHAR(45),
detected_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_read BOOLEAN DEFAULT FALSE,
action_taken VARCHAR(255),
INDEX idx_user_id (user_id),
INDEX idx_detected_at (detected_at)
);
异常检测核心类
<?php
// AnomalyDetection.php
class AnomalyDetection {
private $db;
private $config;
public function __construct($db, $config = []) {
$this->db = $db;
$this->config = array_merge([
'time_window' => 3600, // 1小时的检测窗口
'max_login_attempts' => 10,
'geo_change_alert' => true,
'device_change_alert' => true,
'time_pattern_alert' => true
], $config);
}
/**
* 检测登录异常
*/
public function detectAnomaly($userId, $currentIp, $userAgent, $loginTime = null) {
$loginTime = $loginTime ?? date('Y-m-d H:i:s');
$anomalies = [];
// 1. 检测地理位置变化
if ($this->config['geo_change_alert']) {
$geoAnomaly = $this->detectGeoChange($userId, $currentIp);
if ($geoAnomaly) {
$anomalies[] = $geoAnomaly;
}
}
// 2. 检测设备变化
if ($this->config['device_change_alert']) {
$deviceAnomaly = $this->detectDeviceChange($userId, $userAgent);
if ($deviceAnomaly) {
$anomalies[] = $deviceAnomaly;
}
}
// 3. 检测登录频率异常
$frequencyAnomaly = $this->detectFrequencyAnomaly($userId, $loginTime);
if ($frequencyAnomaly) {
$anomalies[] = $frequencyAnomaly;
}
// 4. 检测异常时间段
if ($this->config['time_pattern_alert']) {
$timeAnomaly = $this->detectTimePatternAnomaly($userId, $loginTime);
if ($timeAnomaly) {
$anomalies[] = $timeAnomaly;
}
}
// 计算风险评分
$riskScore = $this->calculateRiskScore($anomalies);
return [
'is_anomaly' => !empty($anomalies),
'anomalies' => $anomalies,
'risk_score' => $riskScore,
'total_checks' => 4,
'failed_checks' => count($anomalies)
];
}
/**
* 检测地理位置变化
*/
private function detectGeoChange($userId, $currentIp) {
$lastLogin = $this->getLastLogin($userId);
if (!$lastLogin) {
return null;
}
$currentLocation = $this->getLocationFromIp($currentIp);
$lastLocation = $this->getLocationFromIp($lastLogin['ip_address']);
if ($currentLocation && $lastLocation) {
$distance = $this->calculateDistance(
$currentLocation['lat'], $currentLocation['lon'],
$lastLocation['lat'], $lastLocation['lon']
);
// 如果距离超过1000公里且在短时间内,标记为异常
if ($distance > 1000) {
$timeDiff = strtotime(date('Y-m-d H:i:s')) - strtotime($lastLogin['login_time']);
if ($timeDiff < 7200) { // 2小时内跨越1000公里
return [
'type' => 'geo_change',
'severity' => 'high',
'message' => "异常地理位置变化: 从 {$lastLocation['city']} 到 {$currentLocation['city']}",
'distance' => $distance . 'km',
'time_diff' => $timeDiff . '秒'
];
}
}
}
return null;
}
/**
* 检测设备变化
*/
private function detectDeviceChange($userId, $currentUserAgent) {
$lastLogins = $this->getLastLogins($userId, 5);
if (empty($lastLogins)) {
return null;
}
$deviceFingerprint = $this->generateDeviceFingerprint($currentUserAgent);
$knownDevices = [];
foreach ($lastLogins as $login) {
$fingerprint = $this->generateDeviceFingerprint($login['user_agent']);
$knownDevices[$fingerprint] = true;
}
if (!isset($knownDevices[$deviceFingerprint])) {
return [
'type' => 'device_change',
'severity' => 'medium',
'message' => '从未知设备登录',
'device_fingerprint' => $deviceFingerprint
];
}
return null;
}
/**
* 检测登录频率异常
*/
private function detectFrequencyAnomaly($userId, $loginTime) {
$windowStart = date('Y-m-d H:i:s', strtotime($loginTime) - $this->config['time_window']);
$stmt = $this->db->prepare("
SELECT COUNT(*) as count
FROM user_login_logs
WHERE user_id = ?
AND login_time >= ?
AND login_time <= ?
");
$stmt->execute([$userId, $windowStart, $loginTime]);
$result = $stmt->fetch();
if ($result['count'] > $this->config['max_login_attempts']) {
return [
'type' => 'frequency',
'severity' => 'high',
'message' => "短时间内多次登录: {$result['count']} 次在 " . ($this->config['time_window'] / 3600) . " 小时内",
'count' => $result['count'],
'time_window' => $this->config['time_window']
];
}
return null;
}
/**
* 检测异常时间段
*/
private function detectTimePatternAnomaly($userId, $loginTime) {
$hour = date('H', strtotime($loginTime));
$dayOfWeek = date('w', strtotime($loginTime));
// 获取用户通常登录时间段
$stmt = $this->db->prepare("
SELECT HOUR(login_time) as hour,
DAYOFWEEK(login_time) as day_of_week,
COUNT(*) as count
FROM user_login_logs
WHERE user_id = ?
AND login_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP BY HOUR(login_time), DAYOFWEEK(login_time)
ORDER BY count DESC
LIMIT 10
");
$stmt->execute([$userId]);
$patterns = $stmt->fetchAll();
if (!empty($patterns)) {
$usualHours = array_column($patterns, 'hour');
$usualDays = array_column($patterns, 'day_of_week');
if (!in_array($hour, $usualHours) && !in_array($dayOfWeek, $usualDays)) {
return [
'type' => 'time_pattern',
'severity' => 'low',
'message' => "在异常时间段登录: {$hour}:00, 星期" . $dayOfWeek,
'current_hour' => $hour,
'current_day' => $dayOfWeek
];
}
}
return null;
}
/**
* 计算风险评分
*/
private function calculateRiskScore($anomalies) {
$score = 0;
foreach ($anomalies as $anomaly) {
switch ($anomaly['severity']) {
case 'high':
$score += 0.4;
break;
case 'medium':
$score += 0.25;
break;
case 'low':
$score += 0.1;
break;
}
}
return min($score, 1.0);
}
/**
* 获取用户最后登录记录
*/
private function getLastLogin($userId) {
$stmt = $this->db->prepare("
SELECT * FROM user_login_logs
WHERE user_id = ?
AND login_status = 'success'
ORDER BY login_time DESC
LIMIT 1
");
$stmt->execute([$userId]);
return $stmt->fetch();
}
/**
* 获取用户最近登录记录
*/
private function getLastLogins($userId, $limit = 5) {
$stmt = $this->db->prepare("
SELECT * FROM user_login_logs
WHERE user_id = ?
ORDER BY login_time DESC
LIMIT ?
");
$stmt->execute([$userId, $limit]);
return $stmt->fetchAll();
}
/**
* 从IP获取地理位置
*/
private function getLocationFromIp($ip) {
// 可以使用第三方API,如ip-api.com
$response = @file_get_contents("http://ip-api.com/json/{$ip}");
if ($response) {
$data = json_decode($response, true);
if ($data['status'] === 'success') {
return [
'lat' => $data['lat'],
'lon' => $data['lon'],
'city' => $data['city'],
'country' => $data['country']
];
}
}
return null;
}
/**
* 计算两点间的距离(Haversine公式)
*/
private function calculateDistance($lat1, $lon1, $lat2, $lon2) {
$radius = 6371; // 地球半径(km)
$dlat = deg2rad($lat2 - $lat1);
$dlon = deg2rad($lon2 - $lon1);
$a = sin($dlat/2) * sin($dlat/2) +
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
sin($dlon/2) * sin($dlon/2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
return $radius * $c;
}
/**
* 生成设备指纹
*/
private function generateDeviceFingerprint($userAgent) {
return md5($userAgent);
}
}
警报通知系统
<?php
// AlertNotification.php
class AlertNotification {
private $db;
private $emailSender;
public function __construct($db, $emailSender) {
$this->db = $db;
$this->emailSender = $emailSender;
}
/**
* 发送异常登录警报
*/
public function sendAlert($userId, $anomalyData) {
// 获取用户信息
$user = $this->getUserInfo($userId);
$securitySettings = $this->getSecuritySettings($userId);
if (!$securitySettings['suspicious_login_alert']) {
return false;
}
// 记录警报
$alertId = $this->logAlert($userId, $anomalyData);
// 发送通知
$notificationsSent = [];
// 1. 邮件通知
$emailSent = $this->sendEmailAlert($user, $anomalyData);
if ($emailSent) {
$notificationsSent[] = 'email';
}
// 2. 短信通知(如果配置了)
if (!empty($user['phone'])) {
$smsSent = $this->sendSmsAlert($user['phone'], $anomalyData);
if ($smsSent) {
$notificationsSent[] = 'sms';
}
}
// 3. 推送通知(如果系统支持)
if (!empty($user['push_token'])) {
$pushSent = $this->sendPushNotification($user['push_token'], $anomalyData);
if ($pushSent) {
$notificationsSent[] = 'push';
}
}
return [
'alert_id' => $alertId,
'notifications_sent' => $notificationsSent
];
}
/**
* 发送邮件警报
*/
private function sendEmailAlert($user, $anomalyData) {
$subject = "⚠️ 安全警报: 检测到异常登录活动";
$message = "
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.alert-box {
background-color: #fff3cd;
border: 1px solid #ffc107;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.high-risk {
background-color: #f8d7da;
border-color: #f5c6cb;
}
.info {
margin: 10px 0;
padding: 10px;
background-color: #f8f9fa;
border-radius: 5px;
}
</style>
</head>
<body>
<h2>异常登录检测警报</h2>
<div class='alert-box'>
<h3>检测到以下异常:</h3>
<ul>
";
foreach ($anomalyData['anomalies'] as $anomaly) {
$message .= "<li><strong>{$anomaly['type']}:</strong> {$anomaly['message']}</li>";
}
$message .= "
</ul>
</div>
<div class='info'>
<p><strong>风险评分:</strong> " . ($anomalyData['risk_score'] * 100) . "%</p>
<p><strong>登录时间:</strong> " . date('Y-m-d H:i:s') . "</p>
<p><strong>IP地址:</strong> {$this->getClientIp()}</p>
</div>
<div class='actions'>
<h3>建议操作:</h3>
<ul>
<li>如果是您本人操作,请忽略此邮件</li>
<li>如果不是您操作的,请立即修改密码</li>
<li>检查账户安全设置,启用双因素认证</li>
<li>查看最近的登录活动</li>
</ul>
<p>
<a href='https://yourdomain.com/security/check'
style='background-color: #007bff; color: white; padding: 10px 20px;
text-decoration: none; border-radius: 5px;'>
查看安全设置
</a>
</p>
</div>
</body>
</html>
";
return $this->emailSender->sendHtml(
$user['email'],
$subject,
$message
);
}
/**
* 发送短信警报
*/
private function sendSmsAlert($phone, $anomalyData) {
$riskLevel = $anomalyData['risk_score'] > 0.5 ? '高风险' : '中等风险';
$anomalyTypes = array_map(function($a) { return $a['type']; }, $anomalyData['anomalies']);
$message = "[安全警报] 您的账户检测到{$riskLevel}登录异常: "
. implode(', ', $anomalyTypes)
. ",IP: {$this->getClientIp()} 时间: "
. date('H:i:s');
// 使用短信服务发送
return $this->sendSms($phone, $message);
}
/**
* 记录警报到数据库
*/
private function logAlert($userId, $anomalyData) {
$stmt = $this->db->prepare("
INSERT INTO login_alerts
(user_id, alert_type, alert_message, ip_address)
VALUES (?, ?, ?, ?)
");
$stmt->execute([
$userId,
'suspicious_login',
json_encode($anomalyData),
$this->getClientIp()
]);
return $this->db->lastInsertId();
}
/**
* 获取用户信息
*/
private function getUserInfo($userId) {
$stmt = $this->db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]);
return $stmt->fetch();
}
/**
* 获取用户安全设置
*/
private function getSecuritySettings($userId) {
$stmt = $this->db->prepare("
SELECT * FROM user_security_settings WHERE user_id = ?
");
$stmt->execute([$userId]);
return $stmt->fetch() ?: ['suspicious_login_alert' => true];
}
/**
* 获取客户端IP
*/
private function getClientIp() {
$ipAddress = '';
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipAddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipAddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipAddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipAddress = $_SERVER['HTTP_FORWARDED'];
else if(isset($_SERVER['REMOTE_ADDR']))
$ipAddress = $_SERVER['REMOTE_ADDR'];
else
$ipAddress = 'UNKNOWN';
return $ipAddress;
}
}
登录处理集成
<?php
// LoginProcessor.php
class LoginProcessor {
private $db;
private $anomalyDetection;
private $alertNotification;
public function __construct($db) {
$this->db = $db;
$this->anomalyDetection = new AnomalyDetection($db);
$this->alertNotification = new AlertNotification($db, new EmailSender());
}
/**
* 处理登录
*/
public function processLogin($username, $password) {
// 验证用户凭据
$user = $this->authenticateUser($username, $password);
if (!$user) {
$this->logFailedLogin($username);
return ['success' => false, 'message' => '用户名或密码错误'];
}
// 检测登录异常
$clientIp = $this->getClientIp();
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$anomalyResult = $this->anomalyDetection->detectAnomaly(
$user['id'],
$clientIp,
$userAgent
);
// 记录登录日志
$this->logLogin($user['id'], $clientIp, $userAgent,
$anomalyResult['is_anomaly'] ? 'suspicious' : 'success',
$anomalyResult['risk_score']);
// 如果检测到异常,发送警报
if ($anomalyResult['is_anomaly']) {
$alertResult = $this->alertNotification->sendAlert(
$user['id'],
$anomalyResult
);
// 根据风险等级决定是否允许登录
if ($anomalyResult['risk_score'] > 0.7) {
// 高风险:要求额外验证
return [
'success' => false,
'require_verification' => true,
'message' => '检测到高风险登录,需要进行额外验证',
'anomaly' => $anomalyResult,
'alert' => $alertResult
];
}
}
// 安全登录
$_SESSION['user_id'] = $user['id'];
$_SESSION['login_time'] = time();
$_SESSION['login_token'] = bin2hex(random_bytes(32));
return [
'success' => true,
'user' => $user,
'anomaly' => $anomalyResult
];
}
/**
* 记录登录日志
*/
private function logLogin($userId, $ip, $userAgent, $status, $riskScore = 0) {
$stmt = $this->db->prepare("
INSERT INTO user_login_logs
(user_id, login_time, ip_address, user_agent, login_status, risk_score)
VALUES (?, NOW(), ?, ?, ?, ?)
");
$stmt->execute([
$userId,
$ip,
$userAgent,
$status,
$riskScore
]);
}
/**
* 记录失败登录
*/
private function logFailedLogin($username) {
$stmt = $this->db->prepare("
INSERT INTO user_login_logs
(user_id, login_time, ip_address, user_agent, login_status)
VALUES (?, NOW(), ?, ?, 'failed')
");
$stmt->execute([
null,
$this->getClientIp(),
$_SERVER['HTTP_USER_AGENT'] ?? ''
]);
}
/**
* 验证用户凭据
*/
private function authenticateUser($username, $password) {
$stmt = $this->db->prepare("
SELECT * FROM users
WHERE (username = ? OR email = ?)
AND status = 'active'
LIMIT 1
");
$stmt->execute([$username, $username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) {
return $user;
}
return false;
}
private function getClientIp() {
// 同上AlertNotification中的getClientIp方法
// ...
}
}
用户安全面板
<?php
// SecurityDashboard.php
class SecurityDashboard {
private $db;
public function __construct($db) {
$this->db = $db;
}
/**
* 获取用户安全概览
*/
public function getSecurityOverview($userId) {
return [
'recent_logins' => $this->getRecentLogins($userId, 10),
'active_alerts' => $this->getActiveAlerts($userId),
'security_settings' => $this->getSecuritySettings($userId),
'risk_trend' => $this->getRiskTrend($userId, 30)
];
}
/**
* 获取最近登录记录
*/
public function getRecentLogins($userId, $limit = 10) {
$stmt = $this->db->prepare("
SELECT * FROM user_login_logs
WHERE user_id = ?
ORDER BY login_time DESC
LIMIT ?
");
$stmt->execute([$userId, $limit]);
return $stmt->fetchAll();
}
/**
* 获取活跃警报
*/
public function getActiveAlerts($userId) {
$stmt = $this->db->prepare("
SELECT * FROM login_alerts
WHERE user_id = ?
AND is_read = FALSE
ORDER BY detected_at DESC
");
$stmt->execute([$userId]);
return $stmt->fetchAll();
}
/**
* 标记警报为已读
*/
public function markAlertAsRead($alertId, $userId) {
$stmt = $this->db->prepare("
UPDATE login_alerts
SET is_read = TRUE
WHERE id = ? AND user_id = ?
");
return $stmt->execute([$alertId, $userId]);
}
/**
* 获取风险趋势数据
*/
public function getRiskTrend($userId, $days = 30) {
$stmt = $this->db->prepare("
SELECT DATE(login_time) as date,
AVG(risk_score) as avg_risk,
COUNT(*) as login_count,
SUM(CASE WHEN login_status = 'suspicious' THEN 1 ELSE 0 END) as suspicious_count
FROM user_login_logs
WHERE user_id = ?
AND login_time >= DATE_SUB(NOW(), INTERVAL ? DAY)
GROUP BY DATE(login_time)
ORDER BY date DESC
");
$stmt->execute([$userId, $days]);
return $stmt->fetchAll();
}
}
使用示例
<?php
// example_usage.php
// 初始化数据库连接
$db = new PDO('mysql:host=localhost;dbname=your_database', 'username', 'password');
// 登录处理
$loginProcessor = new LoginProcessor($db);
$result = $loginProcessor->processLogin($_POST['username'], $_POST['password']);
if ($result['success']) {
// 登录成功
if (!empty($result['anomaly']['anomalies'])) {
// 有异常但风险较低
$_SESSION['warning'] = '检测到一些异常登录特征,请留意';
}
header('Location: /dashboard');
} else {
if (isset($result['require_verification'])) {
// 需要额外验证
$_SESSION['require_verification'] = true;
$_SESSION['anomaly_data'] = $result['anomaly'];
header('Location: /verify-login');
} else {
// 登录失败
$error = $result['message'];
}
}
// 用户查看安全面板
$securityDashboard = new SecurityDashboard($db);
$securityData = $securityDashboard->getSecurityOverview($_SESSION['user_id']);
// 输出安全面板
echo json_encode($securityData);
前端提醒脚本
<!-- security_alert.js -->
<script>
class SecurityAlertManager {
constructor(options = {}) {
this.options = Object.assign({
checkInterval: 60000, // 每分钟检查一次
apiEndpoint: '/api/security/check-alerts',
soundEnabled: true,
notificationEnabled: true
}, options);
this.init();
}
init() {
// 创建提醒容器
this.createAlertContainer();
// 开始定期检查
this.startPeriodicCheck();
// 监听用户活动
this.monitorUserActivity();
}
createAlertContainer() {
const container = document.createElement('div');
container.id = 'security-alert-container';
container.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
z-index: 10000;
max-width: 400px;
`;
document.body.appendChild(container);
}
startPeriodicCheck() {
this.checkForAlerts();
setInterval(() => this.checkForAlerts(), this.options.checkInterval);
}
async checkForAlerts() {
try {
const response = await fetch(this.options.apiEndpoint, {
headers: {
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
}
});
const data = await response.json();
if (data.alerts && data.alerts.length > 0) {
this.showAlerts(data.alerts);
this.playAlertSound();
if (this.options.notificationEnabled) {
this.showBrowserNotification(data.alerts);
}
}
} catch (error) {
console.error('安全检查失败:', error);
}
}
showAlerts(alerts) {
const container = document.getElementById('security-alert-container');
alerts.forEach(alert => {
const alertElement = this.createAlertElement(alert);
container.appendChild(alertElement);
// 10秒后自动消失
setTimeout(() => {
alertElement.classList.add('fade-out');
setTimeout(() => alertElement.remove(), 500);
}, 10000);
});
}
createAlertElement(alert) {
const severityColors = {
'high': '#dc3545',
'medium': '#ffc107',
'low': '#17a2b8'
};
const color = severityColors[alert.severity] || '#6c757d';
const element = document.createElement('div');
element.style.cssText = `
background: white;
border-left: 4px solid ${color};
border-radius: 4px;
padding: 15px;
margin-bottom: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
animation: slideIn 0.3s ease-out;
`;
element.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: start;">
<h4 style="margin: 0; color: ${color};">
⚠️ ${this.getAlertTypeText(alert.type)}
</h4>
<button onclick="this.parentElement.parentElement.remove()"
style="background: none; border: none; cursor: pointer;">
×
</button>
</div>
<p style="margin: 10px 0 0; color: #666;">
${alert.message}
</p>
<small style="color: #999;">
${new Date(alert.detected_at).toLocaleString()}
</small>
<div style="margin-top: 10px;">
<a href="/security/check" style="color: #007bff; text-decoration: none;">
查看详情 →
</a>
</div>
`;
return element;
}
getAlertTypeText(type) {
const types = {
'geo_change': '地理位置异常',
'device_change': '新设备登录',
'frequency': '登录频率异常',
'time_pattern': '异常登录时间'
};
return types[type] || '安全警报';
}
playAlertSound() {
if (!this.options.soundEnabled) return;
const audio = new Audio();
audio.src = '/sounds/alert.mp3';
audio.volume = 0.3;
audio.play().catch(() => {}); // 忽略自动播放错误
}
showBrowserNotification(alerts) {
if (!('Notification' in window)) return;
if (Notification.permission === 'granted') {
const alertCount = alerts.length;
const body = alertCount > 1
? `发现 ${alertCount} 个安全警报`
: `安全警报: ${alerts[0].message}`;
new Notification('安全警报', {
body: body,
icon: '/images/security-icon.png'
});
} else if (Notification.permission !== 'denied') {
Notification.requestPermission();
}
}
monitorUserActivity() {
// 监听用户离开页面事件
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
this.checkForAlerts();
}
});
}
}
// 初始化安全提醒管理器
document.addEventListener('DOMContentLoaded', () => {
new SecurityAlertManager({
checkInterval: 60000,
soundEnabled: true,
notificationEnabled: true
});
});
</script>
API端点
<?php
// api/security.php
header('Content-Type: application/json');
// CSRF保护
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
http_response_code(403);
die(json_encode(['error' => 'CSRF token mismatch']));
}
}
$action = $_GET['action'] ?? '';
switch ($action) {
case 'check-alerts':
// 检查未读警报
$securityDashboard = new SecurityDashboard($db);
$alerts = $securityDashboard->getActiveAlerts($_SESSION['user_id']);
echo json_encode(['alerts' => $alerts]);
break;
case 'mark-alert-read':
// 标记警报为已读
$alertId = $_POST['alert_id'];
$securityDashboard = new SecurityDashboard($db);
$result = $securityDashboard->markAlertAsRead($alertId, $_SESSION['user_id']);
echo json_encode(['success' => $result]);
break;
case 'login-history':
// 获取登录历史
$securityDashboard = new SecurityDashboard($db);
$history = $securityDashboard->getRecentLogins($_SESSION['user_id'], $_GET['limit'] ?? 10);
echo json_encode(['history' => $history]);
break;
default:
http_response_code(404);
echo json_encode(['error' => 'Invalid action']);
}
这个异常登录检测提醒系统提供了完整的解决方案,包括:
- 多维度异常检测:地理位置、设备、频率、时间段
- 风险评分系统:自动计算登录风险等级
- 多通道通知:邮件、短信、推送通知
- 用户安全面板:查看登录历史和警报记录
- 前端实时提醒:浏览器通知和声音提示
- 安全措施建议:密码修改、双因素认证等
您可以根据实际需求调整检测阈值、通知方式和安全策略。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播