找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2347

积分

0

好友

313

主题
发表于 昨天 19:36 | 查看: 4| 回复: 0

一个黑白对比强烈的抽象图案

一支正在写字的黄色铅笔

前言

今天想分享一个自己动手搭建的、用于记录用户登录日志的小系统。它的核心功能很简单:无论登录成功与否,都能实时捕获用户的登录尝试,并把用户名、密码、来源IP和时间戳等信息规整地记录到 Excel 文件中,方便后续的审计和分析。

本文主要记录一下大体的实现思路和关键代码,希望能给有类似需求的小伙伴提供一个参考。

项目效果

理想状态下,这个系统应该能实时记录所有用户的登录尝试信息,包括输入的用户名、密码、来源IP以及精确的登录时间。所有数据会以 .xlsx 格式保存,结构清晰,可以直接用 Excel 打开查看或进行进一步的数据分析。

技术选型与架构设计

在动手之前,先简单聊聊技术栈的选择:

  • Node.js + Express.js:作为后端服务。Node.js 事件驱动、非阻塞 I/O 的特性,应对并发的登录请求比较合适。Express 框架则能快速搭建起 API 服务。
  • ExcelJS:用来处理 Excel 文件。最初我试过 xlsx 库,但在实际使用中遇到了些稳定性问题。后来换成了功能更丰富、也更稳定的 ExcelJS 库。
  • 原生前端技术:登录界面和日志查看器直接用 HTML、CSS 和 JavaScript 实现。这样做的好处是免去了框架依赖,项目结构简单,加载速度也快。

系统架构

整个系统主要由三个核心部分组成:

  1. 后端服务器 (server.js):提供记录日志、读取日志文件的 API 接口,并负责 Excel 文件的操作。
  2. 登录页面:一个模拟的企业登录界面,用于触发登录行为并发送日志数据。
  3. 日志查看器 (logs-viewer.html):一个简单的 Web 管理界面,用于查看已生成的日志文件列表及其内容。

核心功能实现

整个项目的灵魂,在于几个关键功能的实现。下面我们逐一拆解。

1. 如何准确获取用户的真实 IP 地址?

在网络环境复杂(可能经过代理、CDN)的情况下,直接从请求对象里拿 IP 可能不准确。我们需要优先读取代理服务器转发过来的标准 HTTP 头信息。

function getClientIP(req) {
    // 配置Express信任代理
    app.set('trust proxy', true);
    // 按优先级尝试多种IP头信息
    let ip = req.headers['x-forwarded-for']?.split(',').map(x => x.trim()).shift() ||
             req.headers['x-real-ip'] ||
             req.headers['cf-connecting-ip'] ||
             req.ip ||
             req.connection.remoteAddress ||
             req.socket.remoteAddress ||
             '未知';
    // 处理IPv6映射的IPv4地址
    if (ip && ip.startsWith('::ffff:')) {
        ip = ip.substring(7);
    }
    // 本地地址转换
    if (ip === '::1') {
        ip = '127.0.0.1';
    }
    return ip;
}

获取客户端IP地址的JavaScript函数代码截图

这段代码的逻辑很清晰:按 X-Forwarded-For, X-Real-IP, CF-Connecting-IP 等常见头信息的优先级进行尝试,如果都没有,再降级使用连接本身的远程地址。最后还对 IPv6 映射地址和本地回环地址做了规范化处理。

2. 如何生成并管理 Excel 日志文件?

我们希望日志文件能自动创建、支持追加新记录(而不是覆盖),并且表头样式美观。这对于 ExcelJS 库来说是小菜一碟。

核心思路是:每次收到日志记录请求时,先检查目标 Excel 文件是否存在。如果存在,就读取它并找到(或创建)“登录日志”这个工作表;如果不存在,则新建一个工作簿和工作表。接着,向工作表中追加新的一行数据并保存。

app.post('/api/log-login', async (req, res) => {
    try {
        const { username, password, loginTime } = req.body;
        const clientIP = getClientIP(req);
        const logFileName = 'login_logs.xlsx';
        const logFilePath = path.join(__dirname, 'logs', logFileName);
        let workbook, worksheet;
        // 检查文件是否存在
        if (fs.existsSync(logFilePath)) {
            // 读取现有文件
            workbook = new ExcelJS.Workbook();
            await workbook.xlsx.read(logFilePath);
            worksheet = workbook.getWorksheet('登录日志');
            if (!worksheet) {
                // 创建新工作表
                worksheet = workbook.addWorksheet('登录日志');
                setupWorksheetHeaders(worksheet);
            }
        } else {
            // 创建新文件
            workbook = new ExcelJS.Workbook();
            worksheet = workbook.addWorksheet('登录登录');
            setupWorksheetHeaders(worksheet);
        }
        // 添加新记录
        const newRowNumber = worksheet.rowCount + 1;
        const newRow = worksheet.getRow(newRowNumber);
        newRow.getCell(1).value = username;
        newRow.getCell(2).value = password;
        newRow.getCell(3).value = loginTime;
        newRow.getCell(4).value = clientIP;
        // 保存文件
        await workbook.xlsx.writeToFile(logFilePath);
        res.json({ success: true, message: '登录日志已记录', fileName: logFileName, clientIP: clientIP });
    } catch (error) {
        console.error('记录登录日志失败:', error);
        res.status(500).json({ success: false, message: '记录登录日志失败' });
    }
});

使用ExcelJS处理登录日志写入的JavaScript代码截图

setupWorksheetHeaders 函数负责初始化工作表的表头(比如“用户名”、“密码”、“登录时间”、“登录IP”),并可以设置字体加粗、背景色等样式,让生成的表格更专业。

3. 前端如何无缝集成日志记录?

关键在于,前端在提交登录表单时,无论后端验证是否通过,都要先调用日志记录接口。我们可以把日志记录做成一个独立的函数。

// 记录登录日志到Excel
function logLoginToExcel(username, password, loginTime) {
    fetch('/api/log-login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({
            username: username,
            password: password,
            loginTime: loginTime
        })
    })
    .then(response => response.json())
    .then(data => {
        if (data.success) {
            console.log('登录日志已记录:', data.fileName, 'IP:', data.clientIP);
        } else {
            console.error('记录登录日志失败:', data.message);
        }
    })
    .catch(error => {
        console.error('发送登录日志失败:', error);
    });
}
function login() {
    const username = $('#username').val();
    const password = $('#password').val();
    const loginTime = new Date().toLocaleString('zh-CN');
    // 无论登录是否成功都记录日志
    logLoginToExcel(username, password, loginTime);
    // 继续原有的登录逻辑...
}

前端JavaScript代码截图,展示登录时如何调用日志记录API

这样,日志记录就和业务逻辑解耦了,非常清晰。

4. 如何提供一个便捷的日志管理界面?

一个简单的 Web 界面就能满足基本需求:列出 logs 目录下所有的 .xlsx 文件,点击文件名可以查看文件内容(以 JSON 或表格形式展示),甚至提供下载链接。

// 加载日志文件列表
function loadLogs() {
    fetch('/api/logs')
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                displayLogs(data.logs);
            } else {
                container.innerHTML = '<div class=\"no-logs\">获取日志文件失败:' + data.message + '</div>';
            }
        })
        .catch(error => {
            container.innerHTML = '<div class=\"no-logs\">获取日志文件失败:' + error.message + '</div>';
        });
}
// 查看日志内容
function viewLogContent(filename) {
    fetch('/api/logs/' + filename)
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                displayLogContent(filename, data.data);
            } else {
                alert('获取日志内容失败:' + data.message);
            }
        })
        .catch(error => {
            alert('获取日志内容失败:' + error.message);
        });
}

前端JavaScript代码截图,展示如何加载和查看日志文件

后端对应需要提供 /api/logs (GET) 和 /api/logs/:filename (GET) 两个 API 接口,分别用于返回文件列表和指定文件的内容。

系统工作流程

把上面的模块串起来,整个系统的工作流就非常清晰了:

  1. 用户登录流程

    用户输入账号密码 → 前端记录日志 → 发送到后端API → 获取真实IP → 写入Excel文件 → 返回成功响应
  2. 管理员查看日志流程

    管理员访问查看器 → 获取文件列表 → 选择文件查看内容 → 下载或预览日志数据

最终实现效果

纸上谈兵终觉浅,我们启动项目来看看实际运行效果。

  • 前端登录页面
    模拟的企业登录界面截图
    一个简洁的登录框,用户在此进行登录操作。

  • 后端控制台输出
    Node.js服务器后台输出的详细请求日志记录
    每次有登录请求,后台都会打印出详细的处理日志,包括获取到的IP、文件操作状态等,便于调试和 运维

  • Web日志查看器
    日志查看器Web界面,以表格形式展示登录记录
    在浏览器中可以直接查看日志文件的内容,以表格形式呈现,非常直观。

  • 生成的Excel文件
    用Excel软件打开的登录日志.xlsx文件截图
    最终生成的 .xlsx 文件,可以直接用 Microsoft Excel 或 WPS 等软件打开,支持排序、筛选等所有Excel操作。

总结与思考

通过这个实践项目,我们完成了一个功能完整的登录日志记录系统。从准确获取用户IP,到可靠地写入Excel文件,再到前后端的协同,每一步都采用了相对成熟和稳定的技术方案。

当然,这只是一个基础版本。在实际生产环境中,你可能还需要考虑更多问题,比如日志文件的分割(按天/按月)、日志内容的加密脱敏(特别是密码)、以及更高性能的日志写入方式等。但无论如何,这个项目已经搭建起了一个坚实且可扩展的框架。

希望这篇分享能对你有所启发。如果你对 Node.jsExcel 操作或者其他的全栈开发实践感兴趣,欢迎到 云栈社区 来交流讨论,那里有更多开发者分享的实战经验和开源项目。

一个黄色的卡通太阳表情




上一篇:告别API幻觉!Context7 CLI发布,实时获取Next.js、Tailwind等库最新文档
下一篇:AI代理IDE崛起:构建“智能体指挥中心”管理多代理工作流
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-14 00:07 , Processed in 0.455753 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表