网站首页/ 信息中心/ 档案百科/

零门槛落地档案管理软件隐私保护技术方案

发布时间:2026年07月04日 05:40:24 浏览量:0

一、环境准备与依赖安装

本方案基于 Node.js + PostgreSQL 构建,重点解决档案元数据加密、传输安全及日志脱敏问题。首先需要在服务器或本地开发环境准备基础运行环境。

1. 初始化项目目录

在终端执行以下命令创建项目并初始化 package.json:

mkdir archive-security-demo
cd archive-security-demo
npm init -y

2. 安装核心依赖包

安装 Express 框架、数据库驱动、加密库及 JWT 认证工具:

npm install express pg dotenv jsonwebtoken bcryptjs body-parser

3. 创建环境配置文件

在项目根目录创建 .env 文件,填入以下配置。注意:生产环境必须更换强密码。

PORT=3000
DB_HOST=localhost
DB_PORT=5432
DB_USER=archive_admin
DB_PASSWORD=SecurePass123!
DB_NAME=archive_db
JWT_SECRET=Your_Super_Secret_JWT_Key_Change_Me
ENCRYPTION_KEY=This_is_a_32_byte_long_secret_key!!

二、数据库容器化部署与建表

为了确保环境一致性,使用 Docker 快速启动 PostgreSQL 数据库。如果已安装数据库,可跳过此步直接建表。

1. 启动 PostgreSQL 容器

执行以下命令,映射端口并设置初始密码:

docker run --name archive-secure-db \
-e POSTGRES_PASSWORD=SecurePass123! \
-e POSTGRES_DB=archive_db \
-p 5432:5432 \
-d postgres:15-alpine

2. 初始化数据表结构

连接数据库后,执行以下 SQL 创建用户表与档案表。注意档案表中的 sensitive_data 字段设计为 TEXT 类型,用于存储加密后的 JSON 串。

CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'viewer'
);
CREATE TABLE archives (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
owner_id INTEGER REFERENCES users(id),
-- 存储加密后的敏感信息(如身份证号、家庭住址)
sensitive_data TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

三、核心加密模块实现(AES-256-GCM)

创建 utils/crypto.js 文件。这是隐私保护的核心,采用 AES-256-GCM 算法。该算法不仅提供机密性,还保证数据完整性,能有效防止密文被篡改。

零门槛落地档案管理软件隐私保护技术方案

const crypto = require('crypto');
const algorithm = 'aes-256-gcm';
const keyLength = 32;
const ivLength = 16;
const saltLength = 64;
const tagLength = 16;
const iterations = 100000;
// 从环境变量获取密钥,实际生产中建议使用 KMS 服务
function getKeyFromPassword(password, salt) {
return crypto.pbkdf2Sync(password, salt, iterations, keyLength, 'sha256');
}
/
加密函数
@param {string} text - 明文 JSON 字符串
@returns {string} - 格式为 salt:iv:tag:encrypted 的字符串
/
function encrypt(text) {
const iv = crypto.randomBytes(ivLength);
const salt = crypto.randomBytes(saltLength);
const key = getKeyFromPassword(process.env.ENCRYPTION_KEY, salt);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag();
// 组合存储:salt + iv + tag + encrypted
return `${salt.toString('hex')}:${iv.toString('hex')}:${tag.toString('hex')}:${encrypted}`;
}
/
解密函数
@param {string} encryptedData - 加密字符串
@returns {object} - 解密后的 JSON 对象
/
function decrypt(encryptedData) {
const parts = encryptedData.split(':');
if (parts.length !== 4) throw new Error('Invalid data format');
const salt = Buffer.from(parts[0], 'hex');
const iv = Buffer.from(parts[1], 'hex');
const tag = Buffer.from(parts[2], 'hex');
const encrypted = parts[3];
const key = getKeyFromPassword(process.env.ENCRYPTION_KEY, salt);
const decipher = crypto.createDecipheriv(algorithm, key, iv);
decipher.setAuthTag(tag);
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
module.exports = { encrypt, decrypt };

四、用户身份认证与权限校验

创建 middleware/auth.js。隐私保护的前提是确认访问者身份。这里使用 JWT 进行无状态认证,并在中间件中拦截非法请求。

const jwt = require('jsonwebtoken');
// 模拟的中间件,生产环境请连接数据库验证 Token 黑名单
const authMiddleware = (req, res, next) => {
const token = req.headers['authorization'];
if (!token) {
return res.status(403).json({ error: '未提供访问令牌' });
}
// 移除 "Bearer " 前缀
const tokenString = token.startsWith('Bearer ') ? token.slice(7) : token;
jwt.verify(tokenString, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
return res.status(401).json({ error: '令牌无效或已过期' });
}
// 将用户信息附加到请求对象
req.user = decoded;
next();
});
};
module.exports = { authMiddleware };

五、档案业务接口与日志脱敏

创建 server.js 主文件。本节实现档案的录入(加密存储)与查询(解密展示),并加入日志脱敏函数,防止敏感信息打印在服务器日志中。

require('dotenv').config();
const express = require('express');
const { Pool } = require('pg');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const { encrypt, decrypt } = require('./utils/crypto');
const { authMiddleware } = require('./middleware/auth');
const app = express();
app.use(express.json());
// 数据库连接池配置
const pool = new Pool({
connectionString: `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`
});
// 日志脱敏工具:替换 JSON 字符串中的敏感字段值
const maskLogData = (data) => {
const str = JSON.stringify(data);
return str
.replace(/"idCard":\s"\d{17}[\dXx]/g, '"idCard":""')
.replace(/"phone":\s"\d{11}/g, '"phone":""')
.replace(/"address":\s".+?"/g, '"address":""');
};
//  接口 1: 用户注册
app.post('/api/register', async (req, res) => {
const { username, password } = req.body;
const passwordHash = await bcrypt.hash(password, 10);
try {
const result = await pool.query(
'INSERT INTO users (username, password_hash) VALUES ($1, $2) RETURNING id',
[username, passwordHash]
);
res.json({ userId: result.rows[0].id });
} catch (err) {
res.status(500).json({ error: '注册失败' });
}
});
//  接口 2: 用户登录
app.post('/api/login', async (req, res) => {
const { username, password } = req.body;
const result = await pool.query('SELECT  FROM users WHERE username = $1', [username]);
if (result.rows.length === 0) return res.status(400).json({ error: '用户不存在' });
const user = result.rows[0];
const isValid = await bcrypt.compare(password, user.password_hash);
if (isValid) {
const token = jwt.sign({ id: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token });
} else {
res.status(400).json({ error: '密码错误' });
}
});
//  接口 3: 创建档案(加密存储)
app.post('/api/archives', authMiddleware, async (req, res) => {
const { title, idCard, phone, address } = req.body;
// 1. 构造敏感信息对象
const sensitiveInfo = { idCard, phone, address, ownerId: req.user.id };
// 2. 加密
const encryptedData = encrypt(JSON.stringify(sensitiveInfo));
// 3. 存入数据库
try {
// 打印脱敏后的日志,确保日志不泄露隐私
console.log(`[Audit] User ${req.user.id} creating archive: ${maskLogData(sensitiveInfo)}`);
const result = await pool.query(
'INSERT INTO archives (title, owner_id, sensitive_data) VALUES ($1, $2, $3) RETURNING id',
[title, req.user.id, encryptedData]
);
res.json({ archiveId: result.rows[0].id, status: 'encrypted_stored' });
} catch (err) {
console.error(err);
res.status(500).json({ error: '档案创建失败' });
}
});
//  接口 4: 查询档案(解密展示)
app.get('/api/archives/:id', authMiddleware, async (req, res) => {
const { id } = req.params;
try {
const result = await pool.query('SELECT  FROM archives WHERE id = $1', [id]);
if (result.rows.length === 0) return res.status(404).json({ error: '档案不存在' });
const archive = result.rows[0];
// 权限控制:仅允许创建者查看
if (archive.owner_id !== req.user.id) {
return res.status(403).json({ error: '无权访问该档案' });
}
// 解密数据
const decryptedData = decrypt(archive.sensitive_data);
res.json({
id: archive.id,
title: archive.title,
// 返回解密后的明文数据给前端
data: decryptedData,
created_at: archive.created_at
});
} catch (err) {
console.error(err);
res.status(500).json({ error: '解密失败或数据损坏' });
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`隐私保护服务已启动,端口 ${PORT}`);
});

六、全链路测试验证

启动服务并进行完整流程测试,确保加密与解密逻辑无误。

1. 启动服务

node server.js

2. 注册用户

curl -X POST http://localhost:3000/api/register \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "Admin123!"}'

3. 登录获取 Token

curl -X POST http://localhost:3000/api/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "Admin123!"}'

将返回结果中的 token 值复制出来,例如 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

4. 创建加密档案

提交包含身份证号等敏感信息的数据。观察服务器控制台日志,应显示脱敏后的 ,而非明文。

curl -X POST http://localhost:3000/api/archives \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-d '{
"title": "机密人事档案",
"idCard": "11010519900307234X",
"phone": "13800138000",
"address": "北京市海淀区保密局大院1号"
}'

5. 查询档案验证解密

使用上一步返回的 archiveId 进行查询,应能完整还原明文信息。

curl http://localhost:3000/api/archives/1 \
-H "Authorization: Bearer YOUR_TOKEN_HERE"

6. 数据库直接验证

进入数据库容器查看 archives 表,sensitive_data 字段内容应为乱码密文,确保静态数据安全。

docker exec -it archive-secure-db psql -U archive_admin -d archive_db -c "SELECT sensitive_data FROM archives LIMIT 1;"
档案制度建设:别让教学成果在抽屉里吃灰
档案制度建设:别让教学成果在抽屉里吃灰
这事儿吧,我见过太多学校、培训机构,老师们的教案、课件、学生作品,还有那些获奖记录、教研心得,堆得跟小山似的。要么锁在铁皮柜里,要么散在十几个老师的电脑桌面上。找份三年前的优秀教案?得,跟考古发掘似的...
2026年07月04日 05:40:24
选档案软件别乱买,一定要查档案软件国家档案局资质
选档案软件别乱买,一定要查档案软件国家档案局资质
你是不是刚接了单位采购档案软件的活?挑了大半个月,功能满意价格合适,差点就签合同了。结果前辈随口问一句,有正规资质吗?你一下子就懵了。不少人都踩过这个坑:图便宜买了没资质的软件,最后档案验收通不过,几...
2026年07月04日 05:40:24
档案管理系统信息安全防护薄弱的优化策略与落地方法
档案管理系统信息安全防护薄弱的优化策略与落地方法
【定义】档案管理系统信息安全防护,指通过技术、管理、流程手段保障档案从收集、存储、利用到销毁全生命周期的保密性、完整性、可用性,是《档案法》及国档局《档案信息系统安全等级保护实施指南》明确要求的核心合...
2026年07月04日 05:40:24
微信咨询
电话联系
QQ客服
微信咨询一对一服务
服务热线: 028-8744 4417
QQ客服: 2305721818