如问题所述。我现在有一个过程,用户可以在其中“发布”并将文件上传到我的快速Web服务器,然后将其保存到磁盘上。我的问题是,任何能够访问服务器的人都可以使用该文件并查看其内容。我可以在Express Post处理程序中以任何方式加密/保护文件,以便尽管server.js文件可以打开文件并安全地对其进行“解密”,但用户无法读取/访问保存到磁盘上的内容。执行返回给用户的处理?最好的方法是什么?
您可以使用multer程序包和内置的加密模块上传文件并对其进行加密,然后再存储到磁盘。然后可以将它们解密并通过get路由读取。
文件将以_encrypted.ext的名称保存到./uploads。
可以通过对/ file /:fileName的GET请求检索上载的文件。
我正在使用AES-256-CBC加密文件,但是您可以选择所需的任何算法。显然,您必须更改密钥和/或iv长度。
例如:
const express = require("express");
const port = 8080;
const app = express();
const bodyParser = require("body-parser");
const multer = require("multer");
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const stream = require("stream");
const CryptoAlgorithm = "aes-256-cbc";
// Obviously keys should not be kept in code, these should be populated with environmental variables or key store
const secret = {
iv: Buffer.from('efb2da92cff888c9c295dc4ee682789c', 'hex'),
key: Buffer.from('6245cb9b8dab1c1630bb3283063f963574d612ca6ec60bc8a5d1e07ddd3f7c53', 'hex')
}
app.use(express.static("./public"));
app.use(bodyParser.json());
const storage = multer.memoryStorage()
const upload = multer({ storage });
function encrypt(algorithm, buffer, key, iv) {
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(buffer),cipher.final()]);
return encrypted;
};
function decrypt(algorithm, buffer, key, iv) {
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const decrypted = Buffer.concat([decipher.update(buffer), decipher.final()]);
return decrypted;
}
function saveEncryptedFile(buffer, filePath, key, iv) {
const encrypted = encrypt(CryptoAlgorithm, buffer, key, iv);
if (!fs.existsSync(path.dirname(filePath))) {
fs.mkdirSync(path.dirname(filePath))
}
filePath = path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + "_encrypted" + path.extname(filePath));
fs.writeFileSync(filePath, encrypted);
}
function getEncryptedFile(filePath, key, iv) {
filePath = path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)) + "_encrypted" + path.extname(filePath));
const encrypted = fs.readFileSync(filePath);
const buffer = decrypt(CryptoAlgorithm, encrypted, key, iv);
return buffer;
}
app.post("/upload", upload.single("file"), (req, res, next) => {
console.log("file upload: ", req.file.originalname);
saveEncryptedFile(req.file.buffer, path.join("/uploads", req.file.originalname), secret.key, secret.iv);
// Should set a location header here...
res.status(201).json( { status: "ok" });
});
app.get("/file/:fileName", (req, res, next) => {
console.log("Getting file:", req.params.fileName);
const buffer = getEncryptedFile(path.join("/uploads", req.params.fileName), secret.key, secret.iv);
const readStream = new stream.PassThrough();
readStream.end(buffer);
res.writeHead(200, {
"Content-disposition": "attachment; filename=" + req.params.fileName,
"Content-Type": "application/octet-stream",
"Content-Length": buffer.length
});
res.end(buffer);
});
app.listen(port);
console.log(`Serving at http://localhost:${port}`);