开发网页版加密访问文档

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

步骤1:设置项目环境

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

  1. 初始化项目

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

    sh 复制代码
    npm install express mongoose bcryptjs jsonwebtoken dotenv multer crypto-js
    npm install --save-dev nodemon

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

  1. 创建服务器文件

    在项目根目录下创建server.js文件。

    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文件。

    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文件。

    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文件。

    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文件。

    jsx 复制代码
    // 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;
    jsx 复制代码
    // 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文件。

    jsx 复制代码
    // 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文件,整合上述组件并设置路由。

    jsx 复制代码
    // 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;

总结

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

相关推荐
道一云黑板报8 小时前
前端搭建低代码平台,微前端如何选型?
低代码·arcgis·iframe·微前端·无界·fronts
我不当帕鲁谁当帕鲁17 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
没有出口的猎户座17 小时前
arcgis做buffer
arcgis
GIS思维1 天前
ArcGIS的汉字(亚洲文本)垂直标注
arcgis·arcgis标注·arcgis垂直标注
GIS思维1 天前
ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结
字符编码·arcgis·arcgis pro·arcgis pro属性表乱码·shp编码·shp限制
我不当帕鲁谁当帕鲁2 天前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段方式二
前端·javascript·arcgis
我不当帕鲁谁当帕鲁2 天前
arcgis for js实现popupTemplate弹窗field名称和值转义
前端·javascript·arcgis
啊喔啊喔R2 天前
arcgis pro 学习笔记
笔记·学习·arcgis
fury_1233 天前
layui的table组件中,对某一列的文字设置颜色为浅蓝怎么设置
前端·arcgis·layui
Z_W_H_3 天前
【ArcGISPro】单次将自己建立的工具箱添加至Arcpy中
arcgis