GagandeepS017/privacy-preservation-public-cloud
GitHub: GagandeepS017/privacy-preservation-public-cloud
一个基于 Flask + React 的公有云文件隐私保护项目,通过独立 JWT 认证层确保只有持有有效 token 的数据所有者才能访问云端文件。
Stars: 0 | Forks: 0
# 公有云中的隐私保护
[](https://www.python.org/)
[](https://flask.palletsprojects.com/)
[](https://react.dev/)
[](https://vitejs.dev/)
[](https://jwt.io/)
[](LICENSE)
这是我在 BMS College of Engineering (2021-22) 的工程学士(信息科学)毕业设计项目的参考实现。原始源码已丢失,因此本仓库是一次干净、可运行的重建,忠实于原始项目报告,并使用现代工具链进行了重构,确保能够真正运行。有关各部分如何对应报告内容,请参阅 [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)。(提示:将你的报告 PDF 放在 `docs/capstone-report.pdf` 处,以便与代码保存在一起。)
## 背景
云计算非常便利,但它迫使人们做出艰难的取舍:一旦你上传了文件,云服务提供商的服务器,进而其员工,在技术上就掌握了该文件的密钥。用户失去了对数据存储位置及读取权限的可见性,而且任何来自提供商内部环境的访问,即使是不合法的,看起来也是合法的。报告将其定义为核心问题:数据所有者需要一种在公有云中控制对其自身数据访问权限的方法,确保只有所有者本人才能访问。
本项目用一个简单的想法回答了这个问题。它没有依赖云主机来监督访问,而是在云前端部署了一个独立的认证器。只有携带该认证器签发的 token 的请求才会被视为有效,因此源自云内部的请求(例如,好奇的主机)因为没有 stamp 会被拒绝。其结果是在云服务提供商已有的保护基础之上,增加了一层由所有者控制的隐私保护。
## 功能
公有云用户必须相信云服务提供商不会读取他们的数据。本项目通过在云前端添加一个独立的认证器来消除这一假设:
- 用户通过我们的服务器(而非云主机)进行认证,并接收一个 JWT access token。
- 每个对受保护资源的请求都必须在其 `Authorization: Bearer ` 标头中携带该 token。服务器会对每个请求进行 stamp 和验证。
- 没有 token 会返回 401 Unauthorized。访问他人的文件会返回 403 Forbidden。一个有效且经授权的请求会返回 200 OK。
- token 仅存在于浏览器的 session storage 中,并且在用户注销的瞬间,服务器端会立即将其撤销。
- 一个可选的生物识别第二因素(通过 [Exadel CompreFace](https://github.com/exadel-inc/CompreFace) 进行人脸验证)可以叠加在上面,以实现更高保障级别的登录。
## 架构
```
flowchart LR
U[User / Browser
React app] -->|1. email + password| A[Authenticator
Flask + JWT] A -->|2. signed access token| U U -->|3. request + Bearer token| A A -->|4. verify and stamp| C[(Cloud resources
files / data)] C -->|5. 200 / 401 / 403| U A -.optional.-> F[CompreFace
face verification] ``` 请求生命周期: ``` sequenceDiagram participant B as Browser (React) participant S as Authenticator (Flask) participant DB as SQLite B->>S: POST /api/token {email, password} S->>DB: verify password hash DB-->>S: user record S-->>B: 200 { access_token } (stored in sessionStorage) B->>S: GET /api/hello (Authorization: Bearer)
S-->>B: 200 { message } authorized
B->>S: POST /api/logout (Authorization: Bearer )
S->>S: add token jti to revocation list
S-->>B: 200, token no longer valid
```
## 技术栈
| 层级 | 技术 |
| ---------- | --------------------------------------------------- |
| 前端 | React 18, React Router 6, Vite 5 |
| 后端 | Python 3, Flask, Flask-JWT-Extended, Flask-CORS |
| 认证 | JSON Web Tokens (HS256), Werkzeug password hashing |
| 存储 | SQLite (standard library, zero external DB) |
| 生物识别 | Exadel CompreFace (optional, Docker) |
| 测试 | pytest |
## 快速开始
你需要 Python 3.10+ 和 Node 18+。
### 1. 后端 (API)
```
cd backend
python -m venv venv
# Windows
venv\Scripts\activate
# macOS / Linux
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # Windows: copy .env.example .env
python run.py # http://127.0.0.1:3001
```
首次运行时,系统会创建数据库并注入一个演示账号(`test` / `test`),其中包含几个示例文件。
### 2. 前端 (Web 应用)
在第二个终端中:
```
cd frontend
npm install
npm run dev # http://localhost:3000
```
打开 http://localhost:3000,点击 Login,并使用 `test` / `test` 登录。Vite 开发服务器会将所有 `/api/*` 调用代理到 Flask 后端,因此你只需处理一个源。
## API 参考
Base URL: `http://127.0.0.1:3001`
| 方法 | Endpoint | 认证 | 描述 |
| ------ | ------------------- | ------ | ---------------------------------------------- |
| GET | `/api/health` | none | 存活探针,以及人脸认证是否开启。 |
| POST | `/api/register` | none | 创建一个新用户 `{email, password}`。 |
| POST | `/api/token` | none | 登录;返回 `{ access_token }`。 |
| GET | `/api/me` | Bearer | 当前用户的个人资料。 |
| GET | `/api/hello` | Bearer | 标准的受保护资源。 |
| GET | `/api/files` | Bearer | 列出调用者的云文件。 |
| GET | `/api/files/` | Bearer | 读取一个文件(如果不是所有者则返回 403)。 |
| POST | `/api/logout` | Bearer | 撤销当前 token。 |
| GET | `/api/face/status` | none | 是否已配置 CompreFace。 |
| POST | `/api/face/verify` | Bearer | 通过 CompreFace 验证两个人脸图像 (base64)。 |
## 可选:人脸验证 (CompreFace)
报告中的第二因素使用了 [Exadel CompreFace](https://github.com/exadel-inc/CompreFace),这是一个免费、自托管的人脸识别服务。它默认是禁用的,因此应用无需任何额外基础设施即可运行。要启用它:
1. 使用 Docker 运行 CompreFace(参见他们的[快速开始](https://github.com/exadel-inc/CompreFace#getting-started-with-compreface))。
2. 在 CompreFace UI 中创建一个 Face Verification 服务并复制其 API key。
3. 在 `backend/.env` 中设置:
COMPREFACE_URL=http://localhost:8000
COMPREFACE_API_KEY=
FACE_SIMILARITY_THRESHOLD=0.95
4. 重启后端。`POST /api/face/verify` 现在会代理到 CompreFace,并且只有在相似度超过阈值时才接受登录。
## 测试
```
cd backend
venv\Scripts\activate # or: source venv/bin/activate
pytest -q
```
测试套件涵盖了整个流程:健康检查、登录、错误凭证 (401)、受保护访问 (200)、所有权强制执行 (403)、注册以及基于注销的 token 撤销。
## 项目结构
```
.
├── backend/
│ ├── run.py # dev entry point
│ ├── requirements.txt
│ ├── .env.example
│ ├── src/
│ │ ├── __init__.py # Flask app factory + JWT handlers
│ │ ├── config.py # env-driven configuration
│ │ ├── database.py # SQLite data layer
│ │ ├── auth.py # /register /token /logout /me
│ │ ├── protected.py # /hello /files (token-gated)
│ │ └── face.py # /face/* CompreFace proxy (optional)
│ └── tests/
│ └── test_auth.py
├── frontend/
│ ├── index.html
│ ├── vite.config.js # dev server + /api proxy
│ └── src/
│ ├── main.jsx
│ ├── App.jsx # routes
│ ├── api.js # fetch client + token storage
│ ├── auth/AuthContext.jsx
│ ├── components/ # Navbar, ProtectedRoute
│ └── pages/ # Home, Login, Dashboard, Logout
├── docs/
│ └── ARCHITECTURE.md
├── LICENSE
└── README.md
```
## 路线图
直接来自报告的未来增强功能,外加一些生产环境的注意事项:
- [ ] 将 CompreFace 人脸 token 作为真正的第二因素接入登录流程。
- [ ] 将 token 撤销列表持久化到 Redis 中(目前在进程内)。
- [ ] 文件上传/下载到真正的对象存储(兼容 S3)。
- [ ] Refresh tokens 加上短期的 access tokens。
- [ ] 使用 `docker-compose` 对整个技术栈进行 Docker 化。
## 作者
- Gagandeep S (1BM18IS035)
- Deevith H T (1BM18IS031)
指导老师:Prof. Chandrakala G Raju,BMS College of Engineering,信息科学与工程系。
## 许可证
基于 [MIT License](LICENSE) 发布。
React app] -->|1. email + password| A[Authenticator
Flask + JWT] A -->|2. signed access token| U U -->|3. request + Bearer token| A A -->|4. verify and stamp| C[(Cloud resources
files / data)] C -->|5. 200 / 401 / 403| U A -.optional.-> F[CompreFace
face verification] ``` 请求生命周期: ``` sequenceDiagram participant B as Browser (React) participant S as Authenticator (Flask) participant DB as SQLite B->>S: POST /api/token {email, password} S->>DB: verify password hash DB-->>S: user record S-->>B: 200 { access_token } (stored in sessionStorage) B->>S: GET /api/hello (Authorization: Bearer
示例:登录并调用受保护路由
``` # 1. 获取 token TOKEN=$(curl -s -X POST http://127.0.0.1:3001/api/token \ -H "Content-Type: application/json" \ -d '{"email":"test","password":"test"}' | python -c "import sys,json;print(json.load(sys.stdin)['access_token'])") # 2. 使用它 curl http://127.0.0.1:3001/api/hello -H "Authorization: Bearer $TOKEN" # {"message":"test is successfully logged in for cloud access."} # 3. 没有 token curl -i http://127.0.0.1:3001/api/hello # 401 {"msg":"Missing Authorization Header"} ```标签:Flask, JWT, React, Syscalls, 云存储, 安全规则引擎, 网络安全, 逆向工具, 隐私保护