Files
pdnode-account/README.md
2025-07-30 02:43:49 +00:00

503 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Pdnode Account
**如果你还没了解过oauth[请点这](Oauth.md)**
这是一个支持普通登录注册和OAuth 2.0授权码流程的认证系统,适合自建账号体系和第三方授权。
## 功能特性
### 🔐 用户认证
- 用户注册和登录
- JWT令牌认证
- 密码加密存储
### 🚀 OAuth 2.0 功能
- **Authorization Code Flow** - 完整的授权码流程
- **Access Token** - 访问令牌生成和验证
- **Refresh Token** - 刷新令牌支持
- **Token Revocation** - 令牌撤销功能
- **PKCE Support** - 支持PKCEProof Key for Code Exchange
- **Scope Management** - 权限范围管理
### 🛡️ 安全特性
- 客户端密钥管理
- 令牌过期机制
- 自动清理过期令牌
- 重定向URI验证
- 客户端所有权验证
### 📊 OAuth客户端管理
- 创建OAuth客户端
- 获取客户端列表
- 获取客户端详情
- 获取客户端密钥
- 重置客户端密钥
- 删除客户端
## API端点
### 用户认证
```
POST /api/auth/register - 用户注册
POST /api/auth/login - 用户登录
GET /api/auth/profile - 获取用户信息
```
### OAuth端点
```
GET /api/oauth/authorize - 授权端点
POST /api/oauth/token - 令牌端点
POST /api/oauth/revoke - 撤销端点
GET /api/oauth/userinfo - 用户信息端点
GET /api/oauth/tokeninfo - 令牌信息端点
```
### OAuth客户端管理
```
POST /api/oauth/clients - 创建客户端
GET /api/oauth/clients - 获取客户端列表
GET /api/oauth/clients/:clientId - 获取客户端详情
GET /api/oauth/clients/:clientId/secret - 获取客户端密钥
POST /api/oauth/clients/:clientId/reset-secret - 重置客户端密钥
DELETE /api/oauth/clients/:clientId - 删除客户端
```
### 发现端点
```
GET /.well-known/oauth-authorization-server - OAuth发现端点
```
## 安装和运行
### 1. 安装依赖
```bash
npm install
```
### 2. 配置环境变量
创建 `.env` 文件:
```env
DB_HOST=localhost
DB_PORT=5432
DB_NAME=your_database
DB_USER=your_username
DB_PASSWORD=your_password
JWT_SECRET=your_jwt_secret_key
PORT=3000
```
### 3. 启动服务
```bash
# 开发模式
npm run dev
# 生产模式
npm start
```
## 前端界面
本项目包含两个前端版本:
### 🚀 React + Material-UI 版本(推荐)
现代化的React应用使用Material-UI组件库。
#### 安装和运行
```bash
# 安装前端依赖
npm install
# 启动前端开发服务器
npm run dev:frontend
# 构建生产版本
npm run build:frontend
```
#### 功能特性
-**响应式设计** - 适配各种屏幕尺寸
-**现代化UI** - Material-UI设计语言
-**路由管理** - React Router
-**状态管理** - Context API
-**表单验证** - 实时验证和错误提示
-**加载状态** - 优雅的加载动画
-**错误处理** - 友好的错误提示
#### 页面说明
1. **登录页面** (`/login`)
- 用户名/密码登录
- 密码可见性切换
- 表单验证
- 自动跳转到注册
2. **注册页面** (`/register`)
- 用户注册表单
- 密码确认验证
- 邮箱格式验证
- 自动跳转到登录
3. **个人中心** (`/dashboard`)
- 用户信息展示
- OAuth客户端管理
- 创建/删除客户端
- 退出登录
4. **OAuth授权页面** (`/oauth/authorize`)
- 第三方应用授权
- 权限范围展示
- 用户信息确认
- 授权/拒绝操作
### 📄 HTML + Bootstrap 版本
简单的HTML版本使用Bootstrap样式。
#### 使用方法
```bash
# 直接打开HTML文件
open public/index.html
```
#### 功能特性
-**轻量级** - 无需构建工具
-**Bootstrap样式** - 美观的界面
-**原生JavaScript** - 简单易懂
-**登录/注册切换** - 单页面应用
-**表单验证** - 客户端验证
## 使用示例
### 1. 启动后端服务
```bash
# 启动后端API服务
npm start
```
### 2. 启动前端服务
```bash
# 启动React前端
npm run dev:frontend
```
### 3. 访问应用
- **React版本**: http://localhost:3001
- **HTML版本**: 直接打开 `public/index.html`
### 4. 测试OAuth流程
#### 方法一:使用前端界面
1. 注册/登录用户
2. 在个人中心创建OAuth客户端
3. 访问授权页面:`http://localhost:3001/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:3001/callback&scope=read%20write&state=test123`
4. 在授权页面查看应用信息和请求的权限
5. 选择"同意授权"或"拒绝授权"
6. 系统会重定向到第三方应用并附带授权码或错误信息
#### 方法二:使用第三方应用示例
1. 启动后端和前端服务
2. 在个人中心创建OAuth客户端
3. 打开第三方应用示例:`http://localhost:3001/third-party-app.html`
4. 填入客户端ID和密钥
5. 点击"开始OAuth授权"按钮
6. 完成授权流程并查看API响应
#### 方法三:使用测试脚本
```bash
# 运行完整的OAuth流程测试
npm run test:oauth-flow
```
### 5. OAuth 2.0 授权流程详解
#### 完整的授权码流程 (Authorization Code Flow)
**步骤 1: 获取授权信息**
```
GET /api/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:3001/callback&scope=read%20write&state=test123
```
**响应示例:**
```json
{
"success": true,
"message": "授权信息获取成功",
"data": {
"client": {
"id": "YOUR_CLIENT_ID",
"name": "应用名称",
"description": "应用描述"
},
"scopes": ["read", "write"],
"state": "test123",
"redirect_uri": "http://localhost:3001/callback"
}
}
```
**步骤 2: 用户同意/拒绝授权**
用户在前端授权页面选择同意或拒绝授权:
**同意授权:**
```
POST /api/oauth/authorize/consent
Content-Type: application/json
Authorization: Bearer USER_JWT_TOKEN
{
"client_id": "YOUR_CLIENT_ID",
"redirect_uri": "http://localhost:3001/callback",
"scope": "read write",
"state": "test123",
"approved": true
}
```
**拒绝授权:**
```
POST /api/oauth/authorize/consent
Content-Type: application/json
Authorization: Bearer USER_JWT_TOKEN
{
"client_id": "YOUR_CLIENT_ID",
"redirect_uri": "http://localhost:3001/callback",
"scope": "read write",
"state": "test123",
"approved": false
}
```
**步骤 3: 获取授权码或错误**
- **同意授权**:重定向到 `redirect_uri` 并附带授权码
```
http://localhost:3001/callback?code=AUTH_CODE&state=test123
```
- **拒绝授权**:重定向到 `redirect_uri` 并附带错误信息
```
http://localhost:3001/callback?error=access_denied&error_description=用户拒绝授权&state=test123
```
**步骤 4: 使用授权码交换访问令牌**
```
POST /api/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&code=AUTH_CODE&redirect_uri=http://localhost:3001/callback
```
## 前端技术栈
### React版本
- **React 18** - 用户界面库
- **Material-UI 5** - 组件库
- **React Router 6** - 路由管理
- **Axios** - HTTP客户端
- **Vite** - 构建工具
### HTML版本
- **Bootstrap 5** - CSS框架
- **Font Awesome** - 图标库
- **原生JavaScript** - 交互逻辑
## 开发说明
### 目录结构
```
├── src/ # React源代码
│ ├── components/ # 组件
│ ├── contexts/ # 上下文
│ ├── pages/ # 页面
│ ├── App.jsx # 主应用
│ └── main.jsx # 入口文件
├── public/ # 静态资源
│ └── index.html # HTML版本
├── index.html # React入口
├── vite.config.js # Vite配置
└── package.json # 项目配置
```
### 开发命令
```bash
# 开发模式
npm run dev:frontend
# 构建生产版本
npm run build:frontend
# 预览生产版本
npm run preview:frontend
```
### 环境配置
前端会自动代理API请求到后端
```javascript
// vite.config.js
server: {
port: 3001,
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
}
```
## 安全特性
### 前端安全
- ✅ **JWT令牌管理** - 自动存储和刷新
- ✅ **路由保护** - 私有路由验证
- ✅ **表单验证** - 客户端和服务器端验证
- ✅ **错误处理** - 友好的错误提示
- ✅ **CORS配置** - 跨域请求处理
### 用户体验
- ✅ **响应式设计** - 移动端适配
- ✅ **加载状态** - 优雅的加载动画
- ✅ **错误提示** - 清晰的错误信息
- ✅ **表单验证** - 实时验证反馈
- ✅ **自动跳转** - 智能路由管理
## 数据库结构
### 用户表 (users)
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### OAuth客户端表 (oauth_clients)
```sql
CREATE TABLE oauth_clients (
id SERIAL PRIMARY KEY,
client_id VARCHAR(100) UNIQUE NOT NULL,
client_secret VARCHAR(255) NOT NULL,
name VARCHAR(100) NOT NULL,
description TEXT,
redirect_uris TEXT[] NOT NULL,
scopes TEXT[] DEFAULT ARRAY['read', 'write'],
user_id INTEGER NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### OAuth授权码表 (oauth_auth_codes)
```sql
CREATE TABLE oauth_auth_codes (
id SERIAL PRIMARY KEY,
code VARCHAR(255) UNIQUE NOT NULL,
client_id VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL,
redirect_uri VARCHAR(255) NOT NULL,
scopes TEXT[] NOT NULL,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### OAuth访问令牌表 (oauth_access_tokens)
```sql
CREATE TABLE oauth_access_tokens (
id SERIAL PRIMARY KEY,
token VARCHAR(255) UNIQUE NOT NULL,
client_id VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL,
scopes TEXT[] NOT NULL,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
### OAuth刷新令牌表 (oauth_refresh_tokens)
```sql
CREATE TABLE oauth_refresh_tokens (
id SERIAL PRIMARY KEY,
token VARCHAR(255) UNIQUE NOT NULL,
access_token_id INTEGER REFERENCES oauth_access_tokens(id) ON DELETE CASCADE,
client_id VARCHAR(100) NOT NULL,
user_id INTEGER NOT NULL,
is_revoked BOOLEAN DEFAULT FALSE,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
## 安全特性
### 🔒 令牌安全
- 访问令牌有效期1小时
- 刷新令牌有效期30天
- 授权码有效期10分钟
- 自动清理过期令牌
### 🛡️ 客户端安全
- 客户端密钥加密存储
- 重定向URI验证
- 客户端所有权验证
- 支持客户端密钥重置
### 🔐 认证安全
- JWT令牌认证
- 密码bcrypt加密
- 输入验证和清理
- CORS配置
## 测试
### 运行OAuth测试
```bash
npm run test:oauth
```
### 运行基础API测试
```bash
npm run test
```
## 生产环境建议
### 1. 安全配置
- 使用强密码策略
- 启用HTTPS
- 配置CORS策略
- 设置适当的令牌过期时间
### 2. 性能优化
- 使用Redis缓存令牌
- 数据库连接池优化
- 定期清理过期数据
### 3. 监控和日志
- 添加请求日志
- 监控令牌使用情况
- 错误追踪和告警
### 4. 扩展功能
- 支持多种授权类型
- 添加OAuth客户端应用管理界面
- 实现OAuth 2.1标准
- 支持OpenID Connect
## 许可证
MIT License