Files
2026-04-17 16:27:18 +08:00

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: UUID
    • username: 用户名
    • email: 邮箱
    • avatar: 头像URL
    • casdoorId: Casdoor用户ID
    • createdAt: 创建时间
    • 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授权URL
  • handleCallback(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化部署 已完成
总计 基座功能已完成

注意事项

  1. Casdoor版本: 确保使用v3.18.0,API可能与其他版本不兼容
  2. 回调URL: Casdoor配置的重定向URL必须为 http://localhost:3000/api/auth/callback
  3. Casdoor用户信息端点: v3.x 使用 /api/get-account 而非 /api/userinfo
  4. 网络配置: Docker容器间通信需要使用服务名而非localhost
  5. 数据持久化: SQLite数据库文件需要挂载volume以防数据丢失
  6. useSearchParams: 必须包裹在 Suspense 边界内

后续扩展

  • 角色权限管理 (RBAC)
  • 多租户支持
  • 第三方登录 (GitHub, Google等)
  • 用户资料编辑
  • 审计日志
  • API限流
  • 监控与告警
  • 国际化 (i18n)

参考资源