library-picturebook-activity/backend/docs/TENANT_LOGIN_GUIDE.md
2025-11-23 14:04:20 +08:00

5.6 KiB
Raw Blame History

租户登录使用指南

概述

系统已完整支持多租户登录功能,每个租户可以独立访问系统,数据完全隔离。

租户识别方式

系统支持以下方式识别租户:

1. URL参数方式推荐

在登录页面URL中添加 tenant 参数:

http://your-domain.com/login?tenant=tenant-a

登录页面会自动识别租户编码,并在登录时自动发送。

2. 登录表单输入

如果URL中没有租户参数登录页面会显示租户编码输入框用户可以手动输入。

3. 请求头方式

前端会自动将租户信息添加到所有API请求的请求头中

  • X-Tenant-Code: 租户编码
  • X-Tenant-Id: 租户ID

使用流程

方式一通过URL参数访问推荐

  1. 访问租户登录页面

    http://your-domain.com/login?tenant=tenant-a
    
  2. 输入用户名和密码

    • 用户名:租户内的用户名
    • 密码:用户密码
    • 租户编码已自动填充从URL参数
  3. 登录成功

    • 系统自动保存租户信息到 localStorage
    • 后续所有API请求都会自动携带租户信息
    • 用户只能看到和操作自己租户的数据

方式二:手动输入租户编码

  1. 访问登录页面

    http://your-domain.com/login
    
  2. 输入租户信息

    • 租户编码:输入租户编码(如:tenant-a
    • 用户名:租户内的用户名
    • 密码:用户密码
  3. 登录成功

    • 系统保存租户信息
    • 后续请求自动携带租户信息

后端API使用

登录接口

请求:

POST /api/auth/login
Content-Type: application/json

{
  "username": "user1",
  "password": "password123",
  "tenantCode": "tenant-a"  // 可选,也可以从请求头获取
}

或者通过请求头:

POST /api/auth/login
X-Tenant-Code: tenant-a
Content-Type: application/json

{
  "username": "user1",
  "password": "password123"
}

响应:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": 1,
    "username": "user1",
    "nickname": "用户1",
    "email": "user1@example.com",
    "tenantId": 2,
    "tenantCode": "tenant-a",
    "roles": ["admin"],
    "permissions": ["user:read", "user:create", ...]
  }
}

其他API请求

登录后所有API请求都会自动携带租户信息通过JWT Token或请求头后端会自动过滤数据

GET /api/users
Authorization: Bearer <token>
X-Tenant-Code: tenant-a  # 自动添加

返回的数据只会包含该租户的用户。

前端实现细节

1. 登录页面自动识别租户

登录页面 (Login.vue) 会:

  • 从URL参数 ?tenant=xxx 获取租户编码
  • 如果URL中没有从 localStorage 读取之前保存的租户编码
  • 如果都没有,显示租户输入框

2. 请求拦截器自动添加租户信息

所有API请求都会自动添加租户信息到请求头

// utils/request.ts
service.interceptors.request.use((config) => {
  const tenantCode = getTenantCode();
  const tenantId = getTenantId();
  
  if (tenantCode) {
    config.headers['X-Tenant-Code'] = tenantCode;
  }
  if (tenantId) {
    config.headers['X-Tenant-Id'] = tenantId;
  }
  
  return config;
});

3. 登录后保存租户信息

登录成功后,系统会自动保存:

  • Token
  • 租户编码 (tenantCode)
  • 租户ID (tenantId)

这些信息保存在 localStorage 中,页面刷新后仍然有效。

示例场景

场景1租户A的用户登录

  1. 访问:http://your-domain.com/login?tenant=tenant-a
  2. 输入用户名和密码
  3. 登录后只能看到租户A的数据

场景2租户B的用户登录

  1. 访问:http://your-domain.com/login?tenant=tenant-b
  2. 输入用户名和密码
  3. 登录后只能看到租户B的数据
  4. 租户A的数据完全不可见

场景3超级租户管理员登录

  1. 访问:http://your-domain.com/login?tenant=super
  2. 使用超级管理员账号登录
  3. 可以管理所有租户

注意事项

  1. 租户编码必须唯一每个租户都有唯一的编码code
  2. 用户属于特定租户:用户只能登录到自己所属的租户
  3. 数据完全隔离:不同租户的数据完全隔离,无法互相访问
  4. 租户信息持久化:登录后租户信息保存在 localStorage刷新页面不会丢失
  5. 切换租户:如果需要切换租户,需要先登出,然后使用新的租户编码登录

故障排查

问题1登录时提示"无法确定租户信息"

原因没有提供租户编码或租户ID

解决

  • 在URL中添加 ?tenant=xxx 参数
  • 或者在登录表单中输入租户编码
  • 或者通过请求头 X-Tenant-Code 提供

问题2登录时提示"用户不属于该租户"

原因:用户不属于指定的租户

解决

  • 确认租户编码是否正确
  • 确认用户是否属于该租户
  • 联系管理员检查用户和租户的关联关系

问题3登录后看不到数据

原因:可能是租户信息没有正确传递

解决

  • 检查浏览器控制台的网络请求,确认请求头中是否包含 X-Tenant-Code
  • 检查 localStorage 中是否保存了租户信息
  • 确认后端是否正确识别了租户

开发建议

  1. 使用URL参数方式:这是最用户友好的方式,用户只需要记住租户的访问链接
  2. 提供租户选择器:如果系统需要支持租户切换,可以在前端添加租户选择器
  3. 错误提示优化:当租户信息缺失时,提供清晰的错误提示
  4. 租户信息显示:在用户界面显示当前租户信息,让用户知道自己在哪个租户下操作