开发网页版加密访问文档

开发一个支持加密访问文档的网页版应用程序涉及多个步骤,包括用户认证、文档加密和解密、文件上传和下载,以及确保整个过程中的数据安全性。下面是一个详细的步骤指南:

步骤1:设置项目环境

首先,设置一个新的项目环境。假设你使用的是Node.js和React.js进行前后端开发。

  1. 初始化项目

    npx create-react-app encrypted-docs-app
    cd encrypted-docs-app
    npm init -y
    
  2. 安装必要的依赖

    npm install express mongoose bcryptjs jsonwebtoken dotenv multer crypto-js
    npm install --save-dev nodemon
    

步骤2:设置后端(Node.js + Express)

  1. 创建服务器文件
    在项目根目录下创建server.js文件。

    const express = require('express');
    const mongoose = require('mongoose');
    const dotenv = require('dotenv');
    const cors = require('cors');
    const authRoutes = require('./routes/auth');
    const docRoutes = require('./routes/docs');dotenv.config();
    const app = express();app.use(cors());
    app.use(express.json());mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });app.use('/api/auth', authRoutes);
    app.use('/api/docs', docRoutes);const PORT = process.env.PORT || 5000;
    app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
    
  2. 用户认证
    创建一个新的目录routes,并在其中创建auth.js文件。

    const express = require('express');
    const bcrypt = require('bcryptjs');
    const jwt = require('jsonwebtoken');
    const User = require('../models/User');const router = express.Router();// 注册
    router.post('/register', async (req, res) => {const { username, password } = req.body;const salt = await bcrypt.genSalt(10);const hashedPassword = await bcrypt.hash(password, salt);const newUser = new User({ username, password: hashedPassword });try {const savedUser = await newUser.save();res.status(201).json(savedUser);} catch (err) {res.status(400).json(err);}
    });// 登录
    router.post('/login', async (req, res) => {const { username, password } = req.body;try {const user = await User.findOne({ username });if (!user) return res.status(400).json({ message: "User not found" });const isMatch = await bcrypt.compare(password, user.password);if (!isMatch) return res.status(400).json({ message: "Invalid credentials" });const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });res.status(200).json({ token });} catch (err) {res.status(500).json(err);}
    });module.exports = router;
    
  3. 文档上传和下载
    routes目录下创建docs.js文件。

    const express = require('express');
    const multer = require('multer');
    const jwt = require('jsonwebtoken');
    const fs = require('fs');
    const crypto = require('crypto');
    const path = require('path');const router = express.Router();const storage = multer.diskStorage({destination: (req, file, cb) => {cb(null, 'uploads/');},filename: (req, file, cb) => {cb(null, `${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`);}
    });const upload = multer({ storage });// 中间件验证JWT
    const verifyToken = (req, res, next) => {const token = req.header('x-auth-token');if (!token) return res.status(401).json({ message: 'No token, authorization denied' });try {const decoded = jwt.verify(token, process.env.JWT_SECRET);req.user = decoded;next();} catch (err) {res.status(400).json({ message: 'Token is not valid' });}
    };// 文件加密
    const encryptFile = (filePath) => {const cipher = crypto.createCipher('aes-256-ctr', process.env.ENCRYPTION_SECRET);const input = fs.createReadStream(filePath);const output = fs.createWriteStream(`${filePath}.enc`);input.pipe(cipher).pipe(output);
    };// 文件解密
    const decryptFile = (filePath, res) => {const decipher = crypto.createDecipher('aes-256-ctr', process.env.ENCRYPTION_SECRET);const input = fs.createReadStream(filePath);const output = res;input.pipe(decipher).pipe(output);
    };// 上传文档
    router.post('/upload', verifyToken, upload.single('document'), (req, res) => {const filePath = req.file.path;encryptFile(filePath);fs.unlinkSync(filePath); // 删除原始文件,保留加密文件res.status(200).json({ message: 'File uploaded and encrypted successfully' });
    });// 下载文档
    router.get('/download/:filename', verifyToken, (req, res) => {const filePath = `uploads/${req.params.filename}`;decryptFile(filePath, res);
    });module.exports = router;
    
  4. 创建用户模型
    models目录下创建User.js文件。

    const mongoose = require('mongoose');const UserSchema = new mongoose.Schema({username: { type: String, required: true, unique: true },password: { type: String, required: true },
    });module.exports = mongoose.model('User', UserSchema);
    

步骤3:设置前端(React)

  1. 创建登录和注册页面
    src目录下创建components目录,并在其中创建Login.jsRegister.js文件。

    // src/components/Register.js
    import React, { useState } from 'react';
    import axios from 'axios';const Register = () => {const [username, setUsername] = useState('');const [password, setPassword] = useState('');const handleSubmit = async (e) => {e.preventDefault();try {const res = await axios.post('http://localhost:5000/api/auth/register', { username, password });console.log(res.data);} catch (err) {console.error(err);}};return (<form onSubmit={handleSubmit}><input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" /><input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /><button type="submit">Register</button></form>);
    };export default Register;
    
    // src/components/Login.js
    import React, { useState } from 'react';
    import axios from 'axios';const Login = ({ setToken }) => {const [username, setUsername] = useState('');const [password, setPassword] = useState('');const handleSubmit = async (e) => {e.preventDefault();try {const res = await axios.post('http://localhost:5000/api/auth/login', { username, password });setToken(res.data.token);} catch (err) {console.error(err);}};return (<form onSubmit={handleSubmit}><input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Username" /><input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="Password" /><button type="submit">Login</button></form>);
    };export default Login;
    
  2. 创建文档上传和下载页面
    src/components目录下创建Upload.jsDownload.js文件。

    // src/components/Upload.js
    import React, { useState } from 'react';
    import axios from 'axios';const Upload = ({ token }) => {const [file, setFile] = useState(null);const handleFileChange = (e) => {setFile(e.target.files[0]);};const handleSubmit = async (e) => {e.preventDefault();const formData = new FormData();formData.append('document', file);try {await axios.post('http://localhost:5000/api/docs/upload', formData, {headers: {'Content-Type': 'multipart/form-data','x-auth-token': token}});alert('File uploaded and encrypted successfully');} catch (err) {console.error(err);}};return (<form onSubmit={handleSubmit}>
Upload ); };

export default Upload;


```jsx
// src/components/Download.js
import React, { useState } from 'react';
import axios from 'axios';const Download = ({ token }) => {const [filename, setFilename] = useState('');const handleSubmit = async (e) => {e.preventDefault();try {const res = await axios.get(`http://localhost:5000/api/docs/download/${filename}`, {headers: {'x-auth-token': token},responseType: 'blob'});const url = window.URL.createObjectURL(new Blob([res.data]));const link = document.createElement('a');link.href = url;link.setAttribute('download', filename);document.body.appendChild(link);link.click();} catch (err) {console.error(err);}};return (<form onSubmit={handleSubmit}><input type="text" value={filename} onChange={(e) => setFilename(e.target.value)} placeholder="Filename" /><button type="submit">Download</button></form>);
};export default Download;
  1. 设置App组件和路由
    修改src/App.js文件,整合上述组件并设置路由。

    // src/App.js
    import React, { useState } from 'react';
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    import Login from './components/Login';
    import Register from './components/Register';
    import Upload from './components/Upload';
    import Download from './components/Download';const App = () => {const [token, setToken] = useState('');return (<Router><div><Switch><Route path="/register"><Register /></Route><Route path="/login"><Login setToken={setToken} /></Route><Route path="/upload"><Upload token={token} /></Route><Route path="/download"><Download token={token} /></Route><Route path="/"><h1>Welcome to Encrypted Docs App</h1></Route></Switch></div></Router>);
    };export default App;
    

总结

通过上述步骤,你可以开发一个支持加密访问文档的网页版应用程序。该应用程序包括用户认证、文件上传与下载、文件加密与解密等功能,确保文档的安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/35008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数调用,递归技巧之取反

递归指的是在解决问题的过程中&#xff0c;将问题分解为同类的子问题而解决问题的方法。在程序中通常体现为函数调用自身的方式。 比如是双方回合制对战的游戏进行结算&#xff0c;可以使用一个变量bool类型来完成一回合双方互相战斗并且攻击方同时会作为受攻击方的结算。在递归…

Vue跨标签页数据通信

跨标签页数据通信 在同一浏览器项目地址处于不同的标签页中,建立两个页面间的数据通信&#xff0c;即&#xff1a;B页面新增/修改数据;A页面表格自动更新数据 跨标签页通信常见方案: BroadCast Channel (广播频道) Service Worker LocalStorage Window.onstorage监听 Shared…

English note 1

It was right that I decided not to buy new course before. A few days ago, the after-sales staff of this software announced that all the courses of this software would be taken down. 之前决定不继续买新的课程是对的。几天前&#xff0c;这个软件的售后人员就宣布…

Zookeeper 三、Zookeeper基本使用

1.Zookeeper系统模型 1&#xff09;Zookeeper数据模型之ZNode 在Zookeeper中&#xff0c;数据信息被保存在一个个数据节点上&#xff0c;这些节点被称为ZNode。ZNode是Zookeeper中最小数据单位&#xff0c;在ZNode下面又可以再挂ZNode&#xff0c;这样一层层下去就形成了一个…

Reactor模型:网络线程模型演进

一&#xff0c;阻塞IO线程池模型&#xff08;BIO&#xff09; 这是传统的网络编程方案所采用的线程模型。 即有一个主循环&#xff0c;socket.accept阻塞等待&#xff0c;当建立连接后&#xff0c;创建新的线程/从线程池中取一个&#xff0c;把该socket连接交由新线程全权处理。…

【机器参数】安装适合的nvidia驱动

背景&#xff1a;我现在nvidia-smi没有显示&#xff0c;我的目标是让nvidia-smi正常显示 参考&#xff1a; nchttps://www.cnblogs.com/carle-09/p/11504544.html 可能是驱动版本不对&#xff0c;所以我重新去nvidia官网下载了驱动。 Official Drivers | NVIDIA 得到了NVID…

discuz迪恩cul!教育课程培训网站模板

Discuz x3.2模板 迪恩cul!教育课程培训 GBK&#xff0c;程序包中内附详细的安装教程&#xff0c;下载后按照教程安装即可 discuz迪恩cul!教育课程培训网站模板

如何将本地的Django项目部署到阿里云服务器上?

场景&#xff1a;在本地的pycharm上已经写好了一个Django架构的网站&#xff0c;现在要把它放到公网上 一、阿里云服务器 选择云服务器ECS&#xff0c;新用户可以免费使用三个月 购买时选择预装宝塔面板 买好后&#xff0c;进入云服务器控制台 重置实例密码 远程连接至服务…

python-17-零基础自学python-

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版 知识点&#xff1a; 类、子类、继承、调用函数 练习内容&#xff1a; 练习9-6&#xff1a;冰激凌小店 冰激凌小店是一种特殊的餐馆。编写一个名为IceCreamStand的类&#xff0c;让它继承为完成练习9-1或…

宝塔计划任务调用node程序时,log4js日志保存本地位置会发生变化

接我上一篇文章的情况 超简单的nodejs使用log4js保存日志到本地&#xff08;可直接复制使用&#xff09;-CSDN博客 原本应当保存在node项目目录下的日志文件&#xff0c;如果使用宝塔的计划任务来定时执行的话&#xff0c;日志保存路径会发生变化到如下图的位置&#xff1a; 如…

六款顶级原型设计工具推荐,满足你所有需求!

即时设计作为一款专业原型工具&#xff0c;无论是从功能还是插件库配备情况来看&#xff0c;都是毫无疑问可以进行原型图设计的&#xff0c;而且&#xff0c;即时设计内设海量资源库&#xff0c;可以支持大家通过关键词进行搜索相关资源&#xff0c;并且在线编辑使用&#xff0…

瑜伽馆管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;教练管理&#xff0c;用户管理&#xff0c;瑜伽管理&#xff0c;套餐管理&#xff0c;体测报告管理&#xff0c;基础数据管理 前台账户功能包括&#xff1a;系统首页&#xff0c…

51单片机STC89C52RC——8.1 8*8 LED点阵模块(点亮一个LED)

目录 目的/效果 一&#xff0c;STC单片机模块 二&#xff0c;8*8 LED点阵模块 2.1 电路图 2.1.1 8*8 点阵模块电路图 2.1.2 74HC595&#xff08;串转并&#xff09;模块 电路图 2.1.3 芯片引脚 2.2 引脚电平分析 2.3 74HC595 串转并模块 2.3.1 装弹&#xff08;移位…

2024最新免费版轻量级Navicat Premium Lite 下载和安装教程

2024最新免费版轻量级Navicat Premium Lite 下载和安装教程 关于猫头虎 大家好&#xff0c;我是猫头虎&#xff0c;别名猫头虎博主&#xff0c;擅长的技术领域包括云原生、前端、后端、运维和AI。我的博客主要分享技术教程、bug解决思路、开发工具教程、前沿科技资讯、产品评…

富格林:重视可信经验防止被骗

富格林悉知&#xff0c;现货黄金是一种同时具备流动性强、交易成本低、透明度高等特点的投资品种&#xff0c;因此也吸引了众多投资者的关注和参与。但不少新手投资者&#xff0c;对可信经验不那么重视甚至忽视&#xff0c;往往很容易落入圈套中而遭遇被骗。事实上&#xff0c;…

【C++】————类和对象(下)

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;C 创作时间 &#xff1a;2024年6月25日 一、日期类 首先我们先来看一下通过类实现对日期的一系列处理&#xff0c;同时给大家说一下当中存在的一些细节问题&#xff1a; 1.1 GetMonthDay函数 这个函数的作用就是…

客户有哪些封装案例,一句克服使用让PCBA工厂泪流满面

作者 | 高速先生成员--王辉东 天空下着雨&#xff0c;萧萧从窗前经过&#xff0c;看窗里。 翠萍那娇艳欲滴的脸上挂着两串泪滴。 萧萧一进去&#xff0c;问啥情况。 翠萍往电脑屏幕一指。 当萧萧看向屏幕一瞬间。 那些曾经以为早已遗忘的伤痛&#xff0c;会在某些时刻如潮…

新增题目接口开发

文章目录 1.基本设计2.生成CRUD代码1.生成五张表的代码1.subject_info2.subject_brief3.subject_judge4.subject_multiple5.subject_radio 2.将所有的dao放到mapper文件夹3.将所有实体类使用lombok简化4.删除所有mapper的Param("pageable") Pageable pageable5.删除所…

<Linux> 实现简易线程池

文章目录 ThreadPool.hppThread.hppLockGuard.hppTask.hpptest.cc ThreadPool.hpp #pragma once #include <vector> #include <queue> #include <iostream>#include "Thread.hpp" #include "LockGuard.hpp"#define g_threadPool_num 5 …

【大数据】—谁是世界上最富的人?

引言 在2024年&#xff0c;全球财富的分布再次成为公众和经济学家关注的焦点。随着经济的波动和新兴市场的崛起&#xff0c;亿万富翁的名单也在不断变化。本文将深入探讨这一现象&#xff0c;通过最新的数据可视化分析&#xff0c;揭示世界上最富有的人在2024年的财富状况和趋…