LingAdmin/Backend/LingAdmin.API/USER_MANAGEMENT_API.md

14 KiB
Raw Blame History

用户管理API文档

概述

本文档描述了LingAdmin用户管理系统的API接口包括用户注册、登录、认证和管理功能。

基础信息

  • 基础URL: http://localhost:5000/api
  • 内容类型: application/json
  • 字符编码: UTF-8

认证相关API

1. 用户注册

注册新用户账号。

端点: POST /auth/register

请求体:

{
  "name": "张三",
  "email": "zhangsan@example.com",
  "password": "Password123!",
  "role": "User"  // 可选: "Admin", "User", "Editor"
}

成功响应 (201 Created):

{
  "code": 200,
  "message": "success",
  "data": {
    "id": 11,
    "name": "张三",
    "email": "zhangsan@example.com",
    "role": "User",
    "status": "Active",
    "createdAt": "2026-01-28T09:30:00Z",
    "lastLoginAt": null
  }
}

错误响应 (400 Bad Request):

{
  "code": 400,
  "message": "User with this email already exists",
  "data": null
}

2. 用户登录

用户登录并获取JWT令牌。

端点: POST /auth/login

请求体:

{
  "email": "admin@example.com",
  "password": "Admin123!"
}

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": 1,
      "name": "Admin User",
      "email": "admin@example.com",
      "role": "Admin",
      "status": "Active",
      "createdAt": "2026-01-28T09:00:00Z",
      "lastLoginAt": "2026-01-28T09:30:00Z"
    }
  }
}

错误响应 (401 Unauthorized):

{
  "code": 401,
  "message": "Invalid email or password",
  "data": null
}

注意:

  • 登录成功后返回的token需要保存在客户端localStorage或sessionStorage
  • Token有效期为60分钟可在appsettings.json中配置
  • 已有测试账号:admin@example.com / Admin123!

3. 获取用户资料

获取指定用户的详细信息。

端点: GET /auth/profile/{id}

路径参数:

  • id (integer): 用户ID

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "id": 1,
    "name": "Admin User",
    "email": "admin@example.com",
    "role": "Admin",
    "status": "Active",
    "createdAt": "2026-01-28T09:00:00Z",
    "lastLoginAt": "2026-01-28T09:30:00Z"
  }
}

4. 修改密码

修改当前用户的密码。

端点: POST /auth/change-password/{id}

路径参数:

  • id (integer): 用户ID

请求体:

{
  "currentPassword": "OldPassword123!",
  "newPassword": "NewPassword123!"
}

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "message": "Password changed successfully"
  }
}

错误响应 (400 Bad Request):

{
  "code": 400,
  "message": "Current password is incorrect",
  "data": null
}

用户管理API

5. 获取用户列表

获取所有用户列表(管理员功能)。

端点: GET /users

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": [
    {
      "id": 1,
      "name": "Admin User",
      "email": "admin@example.com",
      "role": "Admin",
      "status": "Active",
      "createdAt": "2026-01-28T09:00:00Z",
      "lastLoginAt": "2026-01-28T09:30:00Z"
    },
    {
      "id": 2,
      "name": "测试用户",
      "email": "test@example.com",
      "role": "User",
      "status": "Active",
      "createdAt": "2026-01-28T10:00:00Z",
      "lastLoginAt": null
    }
  ]
}

6. 获取单个用户

获取指定用户的详细信息。

端点: GET /users/{id}

路径参数:

  • id (integer): 用户ID

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "id": 1,
    "name": "Admin User",
    "email": "admin@example.com",
    "role": "Admin",
    "status": "Active",
    "createdAt": "2026-01-28T09:00:00Z",
    "lastLoginAt": "2026-01-28T09:30:00Z"
  }
}

7. 更新用户信息

更新用户的基本信息(部分更新)。

端点: PUT /users/{id}

路径参数:

  • id (integer): 用户ID

请求体 (所有字段可选):

{
  "name": "新名称",
  "email": "newemail@example.com",
  "role": "Editor",
  "status": "Inactive"
}

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "id": 1,
    "name": "新名称",
    "email": "newemail@example.com",
    "role": "Editor",
    "status": "Inactive",
    "createdAt": "2026-01-28T09:00:00Z",
    "lastLoginAt": "2026-01-28T09:30:00Z"
  }
}

注意:

  • 只需提供要更新的字段
  • 邮箱更新时会检查是否已被其他用户使用

8. 删除用户

删除指定用户。

端点: DELETE /users/{id}

路径参数:

  • id (integer): 用户ID

成功响应 (200 OK):

{
  "code": 200,
  "message": "success",
  "data": {
    "message": "User deleted successfully"
  }
}

数据模型

User (用户)

interface User {
  id: number;              // 用户ID
  name: string;            // 用户名称
  email: string;           // 邮箱地址
  role: string;            // 角色: "Admin" | "User" | "Editor"
  status: string;          // 状态: "Active" | "Inactive"
  createdAt: string;       // 创建时间 (ISO 8601格式)
  lastLoginAt: string | null; // 最后登录时间
}

ApiResponse (统一响应格式)

interface ApiResponse<T> {
  code: number;       // 状态码: 200=成功, 400=客户端错误, 401=未授权, 404=未找到, 500=服务器错误
  message: string;    // 响应消息
  data: T | null;     // 响应数据
}

前端集成示例

React + TypeScript 示例

1. 创建API服务

// src/services/api.ts
import axios from 'axios';

const API_BASE_URL = 'http://localhost:5000/api';

// 创建axios实例
export const apiClient = axios.create({
  baseURL: API_BASE_URL,
  headers: {
    'Content-Type': 'application/json',
  },
});

// 请求拦截器 - 添加token
apiClient.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('authToken');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器 - 处理错误
apiClient.interceptors.response.use(
  (response) => response.data,
  (error) => {
    if (error.response?.status === 401) {
      // 处理未授权 - 清除token并跳转到登录页
      localStorage.removeItem('authToken');
      window.location.href = '/login';
    }
    return Promise.reject(error.response?.data || error);
  }
);

2. 创建认证服务

// src/services/auth.service.ts
import { apiClient } from './api';

interface LoginRequest {
  email: string;
  password: string;
}

interface RegisterRequest {
  name: string;
  email: string;
  password: string;
  role?: string;
}

interface LoginResponse {
  token: string;
  user: User;
}

export const authService = {
  // 登录
  async login(credentials: LoginRequest): Promise<LoginResponse> {
    const response = await apiClient.post('/auth/login', credentials);
    if (response.code === 200) {
      localStorage.setItem('authToken', response.data.token);
      localStorage.setItem('currentUser', JSON.stringify(response.data.user));
    }
    return response.data;
  },

  // 注册
  async register(userData: RegisterRequest): Promise<User> {
    const response = await apiClient.post('/auth/register', userData);
    return response.data;
  },

  // 登出
  logout() {
    localStorage.removeItem('authToken');
    localStorage.removeItem('currentUser');
  },

  // 获取当前用户
  getCurrentUser(): User | null {
    const userStr = localStorage.getItem('currentUser');
    return userStr ? JSON.parse(userStr) : null;
  },

  // 修改密码
  async changePassword(userId: number, passwords: { currentPassword: string; newPassword: string }) {
    const response = await apiClient.post(`/auth/change-password/${userId}`, passwords);
    return response.data;
  },
};

3. 创建用户服务

// src/services/user.service.ts
import { apiClient } from './api';

interface UpdateUserRequest {
  name?: string;
  email?: string;
  role?: string;
  status?: string;
}

export const userService = {
  // 获取所有用户
  async getAllUsers(): Promise<User[]> {
    const response = await apiClient.get('/users');
    return response.data;
  },

  // 获取单个用户
  async getUserById(id: number): Promise<User> {
    const response = await apiClient.get(`/users/${id}`);
    return response.data;
  },

  // 更新用户
  async updateUser(id: number, userData: UpdateUserRequest): Promise<User> {
    const response = await apiClient.put(`/users/${id}`, userData);
    return response.data;
  },

  // 删除用户
  async deleteUser(id: number): Promise<void> {
    await apiClient.delete(`/users/${id}`);
  },
};

4. 登录组件示例

// src/components/Login.tsx
import React, { useState } from 'react';
import { authService } from '../services/auth.service';

export const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();
    setError('');
    setLoading(true);

    try {
      const response = await authService.login({ email, password });
      console.log('登录成功:', response.user);
      // 跳转到主页
      window.location.href = '/dashboard';
    } catch (err: any) {
      setError(err.message || '登录失败,请检查邮箱和密码');
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleLogin}>
      <div>
        <label>邮箱</label>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
      </div>
      <div>
        <label>密码</label>
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />
      </div>
      {error && <div className="error">{error}</div>}
      <button type="submit" disabled={loading}>
        {loading ? '登录中...' : '登录'}
      </button>
    </form>
  );
};

5. 用户列表组件示例

// src/components/UserList.tsx
import React, { useEffect, useState } from 'react';
import { userService } from '../services/user.service';

export const UserList: React.FC = () => {
  const [users, setUsers] = useState<User[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    loadUsers();
  }, []);

  const loadUsers = async () => {
    try {
      const data = await userService.getAllUsers();
      setUsers(data);
    } catch (error) {
      console.error('加载用户失败:', error);
    } finally {
      setLoading(false);
    }
  };

  const handleDelete = async (id: number) => {
    if (confirm('确定要删除此用户吗?')) {
      try {
        await userService.deleteUser(id);
        setUsers(users.filter(u => u.id !== id));
      } catch (error) {
        console.error('删除失败:', error);
      }
    }
  };

  if (loading) return <div>加载中...</div>;

  return (
    <table>
      <thead>
        <tr>
          <th>ID</th>
          <th>姓名</th>
          <th>邮箱</th>
          <th>角色</th>
          <th>状态</th>
          <th>操作</th>
        </tr>
      </thead>
      <tbody>
        {users.map((user) => (
          <tr key={user.id}>
            <td>{user.id}</td>
            <td>{user.name}</td>
            <td>{user.email}</td>
            <td>{user.role}</td>
            <td>{user.status}</td>
            <td>
              <button onClick={() => handleDelete(user.id)}>删除</button>
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};

错误处理

常见状态码

状态码 说明 处理建议
200 成功 正常处理响应数据
400 请求参数错误 检查请求参数格式
401 未授权 清除token跳转到登录页
404 资源未找到 提示用户资源不存在
500 服务器错误 提示用户稍后重试

错误处理示例

try {
  const user = await userService.getUserById(id);
  // 处理成功
} catch (error: any) {
  if (error.code === 404) {
    console.error('用户不存在');
  } else if (error.code === 401) {
    console.error('未授权,请重新登录');
    authService.logout();
    navigate('/login');
  } else {
    console.error('操作失败:', error.message);
  }
}

安全注意事项

  1. Token存储: 建议使用httpOnly Cookie或sessionStorage避免XSS攻击
  2. HTTPS: 生产环境必须使用HTTPS协议
  3. 密码强度: 前端应验证密码强度至少8位包含大小写字母和数字
  4. 输入验证: 前端和后端都应进行输入验证
  5. 错误信息: 避免在错误消息中泄露敏感信息

测试账号

系统提供以下测试账号用于开发测试:

邮箱 密码 角色 说明
admin@example.com Admin123! Admin 管理员账号(需要先注册创建)

注意: 测试环境中的种子数据密码哈希存在问题,建议使用注册接口创建新用户进行测试。


更新日志

v1.0.0 (2026-01-28)

  • 实现用户注册功能
  • 实现用户登录与JWT认证
  • 实现用户信息CRUD操作
  • 实现密码修改功能
  • 集成Dapr事件发布
  • 添加密码安全哈希PBKDF2

技术支持

如有问题,请联系开发团队或查看以下资源:

  • API测试脚本: test-auth.ps1
  • 数据库迁移: Migrations/
  • Swagger文档: http://localhost:5000/swagger(开发环境)

附录

Dapr事件

系统会通过Dapr发布以下事件

  • user-created: 用户注册成功
  • user-login: 用户登录成功
  • user-updated: 用户信息更新
  • user-deleted: 用户被删除
  • user-password-changed: 密码修改成功

前端可以订阅这些事件进行实时更新。