9.1 KiB
9.1 KiB
门户登录基座应用 - 开发计划
项目概述
建立一个门户登录的基座应用,提供基础的用户认证功能,采用前后端分离架构,最终打包为单个Docker镜像部署。
技术栈
后端
- 框架: Node.js + Koa (ES Modules)
- ORM: Prisma v5.22
- 数据库: SQLite
- 认证: OAuth 2.0 / OIDC (对接 Casdoor v3.18.0)
- JWT: jsonwebtoken v9
前端
- 框架: Next.js 16 (App Router)
- React: v19
- TypeScript: v5
- UI组件库: Radix UI + Lucide Icons + TailwindCSS v4
- 状态管理: Zustand v5
- HTTP客户端: Axios
部署
- 容器化: Docker (多阶段构建)
- 反向代理: Nginx
- 认证服务: Casdoor v3.18.0 (本地Docker部署)
项目结构
base-imtim/
├── backend/ # Koa后端服务
│ ├── prisma/ # Prisma ORM配置
│ │ ├── migrations/ # 数据库迁移历史
│ │ └── schema.prisma # 数据模型定义
│ └── src/
│ ├── config/ # 配置文件
│ ├── controllers/ # 控制器
│ ├── middleware/ # 中间件(认证、日志等)
│ ├── routes/ # 路由定义
│ ├── services/ # 业务逻辑
│ └── index.js # 入口文件
├── frontend/ # Next.js前端应用
│ └── src/
│ ├── app/ # App Router页面
│ │ ├── api/ # API代理路由
│ │ ├── dashboard/ # 仪表板(需认证)
│ │ ├── login/ # 登录页
│ │ └── page.tsx # 首页
│ ├── components/ # React组件
│ │ ├── header.tsx # 导航栏
│ │ ├── layout.tsx # 布局组件
│ │ └── protected-route.tsx # 路由守卫
│ └── lib/
│ ├── api.ts # HTTP客户端
│ └── auth-store.ts # 认证状态管理
├── docker/ # Docker配置
│ ├── Dockerfile # 多阶段构建定义
│ ├── nginx.conf # Nginx反向代理配置
│ └── start.sh # 容器启动脚本
├── docs/ # 文档
│ └── casdoor-setup.md # Casdoor配置手册
├── .gitignore # Git忽略规则
├── docker-compose.yml # 开发环境编排
├── PLAN.md # 本文件
└── README.md
功能模块
1. 后端 (Koa)
1.1 核心功能
- 项目初始化 (Koa + 中间件)
- 数据库配置 (SQLite + Prisma)
- 用户模型设计
id: UUIDusername: 用户名email: 邮箱avatar: 头像URLcasdoorId: Casdoor用户IDcreatedAt: 创建时间updatedAt: 更新时间
1.2 认证模块
- Casdoor OAuth 2.0 集成
/api/auth/login- 生成Casdoor登录链接/api/auth/callback- 处理Casdoor回调/api/auth/logout- 登出/api/auth/user- 获取当前用户信息
- JWT Token管理
- 认证中间件
1.3 API路由
POST /api/auth/login # 获取登录URL
GET /api/auth/callback # OAuth回调
POST /api/auth/logout # 登出
GET /api/auth/user # 获取用户信息 (需认证)
GET /api/health # 健康检查
1.4 中间件
- 认证中间件 (验证JWT)
- 错误处理中间件
- 日志中间件
- CORS中间件
2. 前端 (Next.js)
2.1 页面结构
- 首页 (
/) - 登录页 (
/login) - 仪表板 (
/dashboard) - 登录后可见 - API代理路由 (
/api/*)
2.2 核心组件
- Layout (布局组件)
- Header (导航栏 + 用户菜单)
- Footer (页脚)
- LoginButton (登录按钮)
- UserMenu (用户菜单 - Radix Dropdown)
- ProtectedRoute (受保护路由)
2.3 功能实现
- 与后端API对接 (Axios)
- 认证状态管理 (Zustand + localStorage)
- 路由守卫 (未登录跳转)
- 响应式设计 (TailwindCSS v4)
- OAuth回调Token处理
开发步骤
Phase 1: 项目初始化 ✅
1.1 后端初始化
cd backend
npm init -y
npm install koa koa-router koa-bodyparser koa-cors
npm install @prisma/client prisma
npm install jsonwebtoken axios dotenv
初始化Prisma:
npx prisma init
1.2 前端初始化
npx create-next-app@latest frontend --typescript --tailwind --app --src-dir
cd frontend
npm install @radix-ui/react-dialog @radix-ui/react-dropdown-menu
npm install @radix-ui/react-avatar @radix-ui/react-separator
npm install axios zustand lucide-react
Phase 2: 数据库与认证 ✅
2.1 数据库模型
backend/prisma/schema.prisma:
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
id String @id @default(uuid())
username String @unique
email String? @unique
avatar String?
casdoorId String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
运行迁移:
npx prisma migrate dev
npx prisma generate
2.2 Casdoor集成
环境变量配置 (backend/.env):
CASDOOR_SERVER_URL=http://localhost:8000
CASDOOR_CLIENT_ID=your-client-id
CASDOOR_CLIENT_SECRET=your-client-secret
CASDOOR_ORG_NAME=imtim
CASDOOR_APP_NAME=base-imtim
CASDOOR_REDIRECT_URI=http://localhost:3000/api/auth/callback
JWT_SECRET=your-jwt-secret-key
APP_PORT=3001
Phase 3: 后端API开发 ✅
3.1 认证流程实现
1. 用户访问 /login → 点击登录
2. 前端请求后端获取Casdoor登录URL
3. 用户跳转到Casdoor登录
4. 登录成功后Casdoor回调 /api/auth/callback
5. Next.js API路由重定向到后端处理
6. 后端用code换取token,获取用户信息
7. 创建/更新本地用户记录
8. 生成JWT token
9. 重定向到前端dashboard,携带token
10. 前端存储token到localStorage
3.2 核心服务
backend/src/services/auth.service.js:
getLoginUrl()- 生成Casdoor授权URLhandleCallback(code, redirectUri)- 处理OAuth回调verifyToken(token)- 验证JWT
Phase 4: 前端开发 ✅
4.1 认证状态管理
frontend/src/lib/auth-store.ts:
import { create } from 'zustand';
interface AuthState {
user: User | null;
token: string | null;
isAuthenticated: boolean;
login: (token: string, user: User) => void;
logout: () => void;
initialize: () => void;
}
4.2 API代理路由
frontend/src/app/api/auth/*/route.ts:
/api/auth/login- POST - 获取登录URL/api/auth/callback- GET - OAuth回调重定向/api/auth/user- GET - 获取用户信息/api/auth/logout- POST - 登出
4.3 受保护路由
frontend/src/app/dashboard/page.tsx:
- 使用 Suspense 包裹 useSearchParams
- Token从URL参数传递到API请求
- 成功后存储到localStorage
Phase 5: Docker化部署 ✅
5.1 Dockerfile (多阶段构建)
# 阶段1: 构建前端
FROM node:20-alpine AS frontend-builder
WORKDIR /app/frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
# 阶段2: 构建后端
FROM node:20-alpine AS backend-builder
WORKDIR /app/backend
COPY backend/package*.json ./
RUN npm ci
COPY backend/ ./
RUN npx prisma generate
# 阶段3: 生产环境
FROM node:20-alpine AS production
WORKDIR /app
RUN apk add --no-cache nginx
# 复制后端和前端构建
COPY --from=backend-builder /app/backend ./backend
COPY --from=frontend-builder /app/frontend/.next ./frontend/.next
# 安装生产依赖、配置nginx、启动脚本
# ...
5.2 Nginx配置
反向代理配置:
/→ Next.js (3002)/api/→ Koa (3001)
开发状态
| 阶段 | 任务 | 状态 |
|---|---|---|
| Phase 1 | 项目初始化 | ✅ 已完成 |
| Phase 2 | 数据库与认证配置 | ✅ 已完成 |
| Phase 3 | 后端API开发 | ✅ 已完成 |
| Phase 4 | 前端开发 | ✅ 已完成 |
| Phase 5 | Docker化部署 | ✅ 已完成 |
| 总计 | ✅ 基座功能已完成 |
注意事项
- Casdoor版本: 确保使用v3.18.0,API可能与其他版本不兼容
- 回调URL: Casdoor配置的重定向URL必须为
http://localhost:3000/api/auth/callback - Casdoor用户信息端点: v3.x 使用
/api/get-account而非/api/userinfo - 网络配置: Docker容器间通信需要使用服务名而非localhost
- 数据持久化: SQLite数据库文件需要挂载volume以防数据丢失
- useSearchParams: 必须包裹在 Suspense 边界内
后续扩展
- 角色权限管理 (RBAC)
- 多租户支持
- 第三方登录 (GitHub, Google等)
- 用户资料编辑
- 审计日志
- API限流
- 监控与告警
- 国际化 (i18n)