Files
mokeegateway/统一登录网关平台-需求文档.md
2026-07-16 00:04:27 +08:00

755 lines
27 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.
# 统一登录网关平台
## 一、项目概述
### 1.1 项目背景
当前存在多个独立业务系统,各系统均有独立的登录模块、用户体系和权限管理,导致用户需要记忆多套账号密码,管理员需要在多个系统中重复维护用户信息,权限管理混乱且难以统一管控。
### 1.2 项目目标
构建一个统一的多系统登录与权限网关平台,实现:
- 统一登录入口所有业务系统共用一个登录页面https://login.user.mokee.com用户一次登录即可访问所有授权系统
- 统一用户管理:所有用户信息集中在网关平台维护,业务系统不再存储用户数据
- 统一权限管理:所有业务系统的菜单、角色、权限集中在网关平台配置
- 统一接口转发:所有业务系统的接口请求统一经过网关转发,网关负责身份认证和用户信息透传
- 可配置化接入:新增业务系统无需修改网关代码,仅需在后台配置系统信息即可快速接入
- 智能系统跳转:登录成功后自动判断用户绑定系统数量,多系统展示选择页,单系统直接跳转
### 1.3 核心价值
- 提升用户体验:用户无需记忆多套账号密码,一次登录即可访问所有授权系统
- 降低管理成本:管理员只需在一个平台维护用户和权限信息
- 提高系统安全性:统一身份认证和接口鉴权,避免非法访问
- 便于系统扩展:新增业务系统可快速接入,无需重复开发登录和权限模块
---
## 二、技术架构
### 2.1 整体架构图
```
[用户浏览器]
[业务系统前端] → [统一登录页面(https://login.user.zgitm.com)]
[网关服务(32000)] → [认证用户服务(32001)]
↓ ↓
[业务系统后端] ← [业务管理服务(32002)]
[MySQL数据库] ← [Redis缓存]
```
### 2.2 微服务拆分与职责
#### 2.2.1 网关服务mokee-gateway-gateway- 端口32000
- 统一入口:所有业务系统的接口请求和页面访问统一经过网关
- 路由转发:根据配置的系统信息,将请求转发到对应的业务系统后端
- 身份认证校验请求中的Token有效性拦截未登录请求
- 信息透传将用户ID、用户名、角色、岗位、系统ID等信息注入请求头传递给业务系统后端
- 接口鉴权:校验请求接口是否在业务系统的放行列表中
#### 2.2.2 认证用户服务mokee-gateway-auth- 端口32001
- 登录认证处理用户登录请求验证账号密码生成Token
- 用户管理:维护用户基本信息、用户与系统的绑定关系
- 权限管理:维护角色、菜单信息,用户与角色的绑定关系
- 会话管理管理Redis中的用户登录会话处理退出登录请求
- 基础接口:提供获取用户信息、系统信息、菜单路由等基础接口
- 系统选择:登录成功后判断用户绑定系统数量,返回系统列表或直接跳转
#### 2.2.3 业务管理服务mokee-gateway-admin- 端口32002
- 系统管理:维护业务系统的基本信息、域名配置、接口放行列表
- 数据字典:维护全局通用的数据字典
- 日志管理:记录用户登录日志和系统操作日志
- 定时任务:执行系统定时任务,如自动锁定长期未登录用户
### 2.3 技术栈明细
| 技术领域 | 技术选型 | 版本要求 |
|---------|---------|---------|
| 后端框架 | Spring Boot | 3.0+ |
| 开发语言 | Java | 17.0.12+ |
| 前端框架 | Vue3 | 最新稳定版 |
| 数据库 | MySQL | 8.0+ |
| 缓存 | Redis | 最新稳定版 |
| 服务通信 | OpenFeign | Spring Boot 3配套版本 |
| 日志 | SLF4J + Logback | Spring Boot 3配套版本 |
| 部署 | Kubernetes | 用户自行部署 |
### 2.4 环境配置
#### 2.4.1 数据库配置
```yaml
spring:
datasource:
url: jdbc:mysql://db1.prod.zgitm.com:3306/mokeegateway?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: mokeegateway
password: mokee.
driver-class-name: com.mysql.cj.jdbc.Driver
```
#### 2.4.2 Redis配置
```yaml
spring:
redis:
host: redis.db1.zgitm.com
port: 6379
database: 1
password: mokee2016.
timeout: 3000ms
```
#### 2.4.3 开发环境配置
- JDK路径E:\javaJdk\jdk-17.0.12
- Maven路径E:\apache-maven-3.6.0
- 统一登录平台本地开发地址http://127.0.0.1:3300
- 统一登录平台生产域名https://login.user.zgitm.com
---
## 三、核心功能实现
### 3.1 统一登录功能(新增系统选择页)
#### 3.1.1 登录流程(修订版)
1. 用户访问任意业务系统前端域名
2. 业务系统前端检测本地无有效Token自动跳转至统一登录页面https://login.user.mokee.com
3. 跳转时携带回调参数redirect=当前业务系统完整地址(可选,若用户直接访问登录页则无此参数)
4. 用户在统一登录页面输入账号/邮箱+密码
5. 认证用户服务验证账号密码验证通过后生成Token
6. 将Token和用户信息存入Redis设置过期时间
7. 系统选择逻辑:
- 查询当前用户绑定的所有启用状态的业务系统
- 若用户只绑定了1个系统自动跳转至该系统的前端地址
- 若用户绑定了多个系统:跳转至网关平台的系统选择页面,展示所有可访问系统列表
- 用户点击选择目标系统后,跳转至对应系统的前端地址
8. 业务系统前端将Token存入本地存储
#### 3.1.2 系统选择页面功能
- 展示用户所有可访问的业务系统卡片(包含系统名称、系统图标、系统描述)
- 点击系统卡片自动跳转至对应系统的前端地址
- 支持退出登录功能,跳转回统一登录页
- 页面适配PC端和移动端
#### 3.1.3 登录成功返回信息
```json
{
"code": 200,
"msg": "登录成功",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"userId": "123e4567-e89b-12d3-a456-426614174000",
"username": "张三",
"email": "zhangsan@example.com",
"phone": "13800138000",
"avatar": "https://example.com/avatar.jpg",
"post": "产品经理"
},
"systemList": [
{
"systemId": "456e4567-e89b-12d3-a456-426614174001",
"systemCode": "msg",
"systemName": "信息管理系统",
"frontUrl": "https://web.msg.mokee.com"
},
{
"systemId": "789e4567-e89b-12d3-a456-426614174002",
"systemCode": "oa",
"systemName": "办公自动化系统",
"frontUrl": "https://web.oa.mokee.com"
}
],
"needSelectSystem": true
},
"timestamp": 1718000000000
}
```
### 3.2 系统配置功能
#### 3.2.1 系统信息配置
每个业务系统需要配置以下信息:
- 系统编码唯一标识业务系统的字符串msg、oa、finance
- 系统名称:业务系统的中文名称(如:信息管理系统、办公自动化系统)
- 系统前端地址业务系统前端的访问域名https://web.msg.mokee.com
- 系统后端地址业务系统后端的真实服务地址https://server.msg.mokee.com
- 网关API域名业务系统专用的 API 域名DNS 指向网关服务器https://or.test.mokee.com网关通过域名自动识别业务系统
- 系统图标:系统选择页面展示的图标
- 系统状态:启用/禁用
- 系统描述:业务系统的简要说明
#### 3.2.2 接口放行配置
每个业务系统需要配置允许访问的接口列表:
- 接口路径:接口的请求路径(如:/zgapi/v1/user/list
- 请求方式GET/POST/PUT/DELETE
- 接口名称:接口的中文名称
- 接口状态:启用/禁用
### 3.3 接口转发功能
#### 3.3.1 转发流程
1. 业务系统前端使用独立的 API 域名DNS 指向网关),携带 Token 发起接口请求
2. 网关服务从请求头中获取Token校验Token有效性
3. 从Redis中获取用户信息和当前系统信息
4. 根据请求的 Host 头域名,匹配对应业务系统的 gateway_url自动识别业务系统
5. 校验请求接口是否在该业务系统的放行列表中
6. 注入请求头信息将用户ID、用户名、角色、岗位、系统ID等信息注入请求头
7. 将请求转发到业务系统的真实后端地址
8. 将业务系统后端的响应返回给前端
#### 3.3.2 请求头注入信息(完整)
网关服务在转发请求时,会在请求头中注入以下信息,业务系统后端直接从请求头获取即可:
| 请求头字段 | 说明 |
|-----------|------|
| X-User-Id | 当前登录用户的唯一IDUUID |
| X-User-Name | 当前登录用户的真实姓名 |
| X-User-Account | 当前登录用户的登录账号 |
| X-User-Email | 当前登录用户的邮箱 |
| X-User-Post | 当前登录用户的岗位 |
| X-User-Roles | 当前用户在该系统下的角色列表JSON数组字符串 |
| X-System-Id | 当前访问的业务系统ID |
| X-System-Code | 当前访问的业务系统编码 |
| X-System-Name | 当前访问的业务系统名称 |
#### 3.3.3 业务系统后端处理
业务系统后端无需实现任何登录和权限逻辑,只需从请求头中获取上述用户和系统信息,进行业务处理和数据隔离即可。
### 3.4 菜单与权限管理
#### 3.4.1 菜单配置
每个业务系统的菜单在网关平台配置,包括:
- 菜单名称
- 菜单路径
- 前端组件路径
- 菜单图标
- 菜单类型(目录/菜单/按钮)
- 排序
- 状态
#### 3.4.2 角色管理
每个业务系统可以创建多个角色,角色与菜单绑定:
- 角色名称
- 角色编码
- 角色描述
- 绑定的菜单列表
#### 3.4.3 用户授权
用户与业务系统绑定,在每个业务系统下可以分配一个或多个角色:
- 用户绑定业务系统
- 在业务系统下为用户分配角色
- 用户的权限为所分配角色的权限合并
#### 3.4.4 动态路由生成
业务系统前端登录成功后,向网关请求当前用户在该系统下的菜单路由:
1. 前端携带Token请求菜单接口网关通过域名自动识别系统
2. 认证用户服务查询用户在该系统下的所有角色
3. 合并所有角色的菜单权限
4. 生成Vue动态路由JSON返回给前端
5. 前端根据路由JSON动态生成路由并渲染页面
### 3.5 日志管理
#### 3.5.1 登录日志
记录所有用户的登录信息,包括:
- 用户ID
- 用户名
- 登录时间
- 登录IP
- 登录系统
- 登录状态(成功/失败)
- 浏览器信息
- 操作系统信息
#### 3.5.2 操作日志
通过AOP切面自动记录所有用户的操作信息包括
- 操作人ID
- 操作人名称
- 操作时间
- 操作模块
- 操作类型(新增/编辑/删除/查询)
- 请求地址
- 请求方式
- 请求参数
- 响应结果
- 操作状态(成功/失败)
### 3.6 定时任务
系统内置定时任务:
- 自动锁定长期未登录用户每日扫描用户登录日志自动锁定连续1年未登录的用户账号
- 清理过期日志:定期清理超过保留期限的登录日志和操作日志
---
## 四、数据库设计
### 4.1 核心数据表
#### 4.1.1 系统表sys_system
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| system_id | varchar(36) | 是 | 系统IDUUID |
| system_code | varchar(64) | 否 | 系统编码(唯一) |
| system_name | varchar(128) | 否 | 系统名称 |
| front_url | varchar(256) | 否 | 系统前端地址 |
| backend_url | varchar(256) | 否 | 系统后端真实地址 |
| gateway_url | varchar(256) | 否 | 网关代理地址(唯一) |
| icon | varchar(256) | 否 | 系统图标地址 |
| status | tinyint | 否 | 系统状态0-禁用1-启用) |
| description | text | 否 | 系统描述 |
| create_time | datetime | 否 | 创建时间 |
| update_time | datetime | 否 | 更新时间 |
#### 4.1.2 系统接口表sys_system_api
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| api_id | varchar(36) | 是 | 接口IDUUID |
| system_id | varchar(36) | 否 | 关联系统ID |
| api_path | varchar(256) | 否 | 接口路径 |
| api_method | varchar(16) | 否 | 请求方式 |
| api_name | varchar(128) | 否 | 接口名称 |
| status | tinyint | 否 | 接口状态0-禁用1-启用) |
| create_time | datetime | 否 | 创建时间 |
| update_time | datetime | 否 | 更新时间 |
#### 4.1.3 用户表sys_user
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| user_id | varchar(36) | 是 | 用户IDUUID |
| username | varchar(64) | 否 | 登录账号(唯一) |
| password | varchar(128) | 否 | 加密密码 |
| email | varchar(64) | 否 | 邮箱(唯一) |
| phone | varchar(32) | 否 | 手机号 |
| real_name | varchar(64) | 否 | 真实姓名 |
| avatar | varchar(256) | 否 | 头像地址 |
| post | varchar(64) | 否 | 岗位 |
| status | tinyint | 否 | 用户状态0-禁用1-正常) |
| last_login_time | datetime | 否 | 最后登录时间 |
| create_time | datetime | 否 | 创建时间 |
| update_time | datetime | 否 | 更新时间 |
#### 4.1.4 用户系统关联表sys_user_system
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| id | varchar(36) | 是 | 关联IDUUID |
| user_id | varchar(36) | 否 | 用户ID |
| system_id | varchar(36) | 否 | 系统ID |
| create_time | datetime | 否 | 绑定时间 |
#### 4.1.5 角色表sys_role
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| role_id | varchar(36) | 是 | 角色IDUUID |
| system_id | varchar(36) | 否 | 关联系统ID |
| role_name | varchar(64) | 否 | 角色名称 |
| role_code | varchar(64) | 否 | 角色编码 |
| description | text | 否 | 角色描述 |
| status | tinyint | 否 | 角色状态0-禁用1-启用) |
| create_time | datetime | 否 | 创建时间 |
| update_time | datetime | 否 | 更新时间 |
#### 4.1.6 用户角色关联表sys_user_role
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| id | varchar(36) | 是 | 关联IDUUID |
| user_id | varchar(36) | 否 | 用户ID |
| system_id | varchar(36) | 否 | 系统ID |
| role_id | varchar(36) | 否 | 角色ID |
| create_time | datetime | 否 | 绑定时间 |
#### 4.1.7 菜单表sys_menu
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| menu_id | varchar(36) | 是 | 菜单IDUUID |
| system_id | varchar(36) | 否 | 关联系统ID |
| parent_id | varchar(36) | 否 | 父菜单ID |
| menu_name | varchar(64) | 否 | 菜单名称 |
| menu_path | varchar(256) | 否 | 菜单路径 |
| component | varchar(256) | 否 | 前端组件路径 |
| icon | varchar(128) | 否 | 菜单图标 |
| menu_type | tinyint | 否 | 菜单类型1-目录2-菜单3-按钮) |
| permission | varchar(128) | 否 | 权限标识 |
| sort | int | 否 | 排序 |
| status | tinyint | 否 | 菜单状态0-禁用1-启用) |
| create_time | datetime | 否 | 创建时间 |
| update_time | datetime | 否 | 更新时间 |
#### 4.1.8 角色菜单关联表sys_role_menu
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| id | varchar(36) | 是 | 关联IDUUID |
| role_id | varchar(36) | 否 | 角色ID |
| menu_id | varchar(36) | 否 | 菜单ID |
#### 4.1.9 登录日志表sys_login_log
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| log_id | varchar(36) | 是 | 日志IDUUID |
| user_id | varchar(36) | 否 | 用户ID |
| username | varchar(64) | 否 | 登录账号 |
| system_id | varchar(36) | 否 | 登录系统ID |
| login_ip | varchar(64) | 否 | 登录IP |
| login_time | datetime | 否 | 登录时间 |
| status | tinyint | 否 | 登录状态0-失败1-成功) |
| browser | varchar(64) | 否 | 浏览器信息 |
| os | varchar(64) | 否 | 操作系统信息 |
#### 4.1.10 操作日志表sys_operation_log
| 字段名 | 数据类型 | 主键 | 说明 |
|-------|---------|------|------|
| log_id | varchar(36) | 是 | 日志IDUUID |
| user_id | varchar(36) | 否 | 操作人ID |
| username | varchar(64) | 否 | 操作人名称 |
| system_id | varchar(36) | 否 | 操作系统ID |
| module | varchar(64) | 否 | 操作模块 |
| operation | varchar(32) | 否 | 操作类型 |
| request_url | varchar(256) | 否 | 请求地址 |
| request_method | varchar(16) | 否 | 请求方式 |
| request_param | text | 否 | 请求参数 |
| response_result | text | 否 | 响应结果 |
| status | tinyint | 否 | 操作状态0-失败1-成功) |
| operation_time | datetime | 否 | 操作时间 |
---
## 五、接口规范
### 5.1 统一返回格式
所有接口统一返回以下格式:
```json
{
"code": 200,
"msg": "操作成功",
"data": {},
"timestamp": 1718000000000
}
```
- code响应状态码200表示成功其他表示失败
- msg响应消息
- data响应数据
- timestamp响应时间戳
### 5.2 主要接口列表
#### 5.2.1 认证接口
| 接口地址 | 请求方式 | 接口描述 |
|---------|---------|---------|
| /zgapi/v1/auth/login | POST | 用户登录 |
| /zgapi/v1/auth/logout | POST | 退出登录 |
| /zgapi/v1/auth/user/info | GET | 获取当前用户信息 |
| /zgapi/v1/auth/menu/router | GET | 获取当前用户菜单路由 |
| /zgapi/v1/auth/password/update | PUT | 修改密码 |
| /zgapi/v1/auth/system/list | GET | 获取当前用户可访问系统列表 |
---
## 六、外部系统对接网关平台申请说明文档
> 注:在系统管理列表中,新增文档列,点击可以查看系统对接文档的超链接,这个是不要认证直接访问的。
### 6.1 对接前提
1. 已在网关平台后台完成业务系统信息配置系统编码、前端地址、后端地址、网关API域名
2. 业务系统的 API 域名 DNS 已指向网关服务器,网关通过域名自动识别业务系统
3. 已在网关平台后台配置业务系统需要放行的接口列表
4. 已在网关平台后台为用户分配该业务系统的访问权限和角色
### 6.2 前端系统修改步骤
#### 6.2.1 移除原有登录功能
- 删除业务系统原有的登录页面、登录接口、登录逻辑
- 删除业务系统原有的本地用户存储、Token管理逻辑
#### 6.2.2 配置全局路由守卫(核心)
在业务系统的router/index.ts中添加全局路由守卫实现未登录自动跳转统一登录页
```typescript
import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/stores/user'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// 业务系统原有路由(无需保留登录路由)
]
})
// 全局路由守卫
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
const token = localStorage.getItem('token')
// 统一登录平台地址
const LOGIN_URL = 'https://login.mokeeuserlogin.com'
// 当前业务系统编码(从网关平台获取,用于登录回调参数)
const SYSTEM_CODE = 'msg'
if (!token) {
// 未登录,跳转到统一登录页,携带当前页面地址作为回调
window.location.href = `${LOGIN_URL}?redirect=${encodeURIComponent(window.location.href)}&systemCode=${SYSTEM_CODE}`
return
}
// 已登录,继续访问
next()
})
export default router
```
#### 6.2.3 配置全局请求拦截器
在业务系统的utils/request.ts中配置全局请求拦截器统一携带Token。
> **重要说明**:业务系统使用独立的 API 域名(如 `https://or.test.mokee.com`DNS 指向网关服务器。网关通过请求的 Host 头域名自动识别业务系统,前端无需再发送 `X-System-Code` 请求头。
```typescript
import axios from 'axios'
const service = axios.create({
// 业务系统独立的 API 域名DNS 指向网关,从网关平台获取)
baseURL: 'https://or.test.mokee.com',
timeout: 30000
})
// 请求拦截器
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
(response) => {
return response.data
},
(error) => {
// 401未授权跳转到统一登录页
if (error.response && error.response.status === 401) {
localStorage.removeItem('token')
window.location.href = 'https://login.mokeeuserlogin.com'
}
return Promise.reject(error)
}
)
export default service
```
#### 6.2.4 实现动态路由加载
在业务系统的main.ts中添加动态路由加载逻辑
```typescript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { useUserStore } from './stores/user'
const app = createApp(App)
// 初始化时加载动态路由
const initApp = async () => {
const userStore = useUserStore()
const token = localStorage.getItem('token')
if (token) {
try {
// 从网关获取当前用户在该系统下的菜单路由
const res = await userStore.getMenuRouter()
// 动态添加路由
res.data.forEach((route) => {
router.addRoute(route)
})
} catch (error) {
console.error('加载动态路由失败', error)
localStorage.removeItem('token')
window.location.href = 'https://login.mokeeuserlogin.com'
}
}
app.use(router)
app.mount('#app')
}
initApp()
```
#### 6.2.5 获取用户信息
在业务系统的stores/user.ts中实现获取用户信息和菜单路由的方法
```typescript
import { defineStore } from 'pinia'
import request from '@/utils/request'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
menuList: []
}),
actions: {
// 获取当前用户信息
async getUserInfo() {
const res = await request.get('/api/v1/auth/user/info')
this.userInfo = res.data
return res.data
},
// 获取当前用户菜单路由
async getMenuRouter() {
const res = await request.get('/api/v1/auth/menu/router', {
params: {
systemCode: 'msg'
}
})
this.menuList = res.data
return res.data
}
}
})
```
### 6.3 后端系统修改步骤
#### 6.3.1 移除原有登录和权限逻辑
- 删除业务系统原有的登录接口、用户表、角色表、权限表
- 删除业务系统原有的Token校验、权限拦截逻辑
#### 6.3.2 从请求头获取用户信息(核心)
业务系统后端无需访问网关所有用户和系统信息都从网关注入的请求头中获取。以下是Java示例
```java
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1/user")
public class UserController {
@GetMapping("/current")
public UserInfo getCurrentUser(HttpServletRequest request) {
// 从请求头获取用户信息
String userId = request.getHeader("X-User-Id");
String userName = request.getHeader("X-User-Name");
String userAccount = request.getHeader("X-User-Account");
String userEmail = request.getHeader("X-User-Email");
String userPost = request.getHeader("X-User-Post");
String userRoles = request.getHeader("X-User-Roles");
String systemId = request.getHeader("X-System-Id");
String systemCode = request.getHeader("X-System-Code");
// 构建用户信息对象
UserInfo userInfo = new UserInfo();
userInfo.setUserId(userId);
userInfo.setUserName(userName);
userInfo.setUserAccount(userAccount);
userInfo.setUserEmail(userEmail);
userInfo.setUserPost(userPost);
// 解析角色列表
userInfo.setRoles(JSON.parseArray(userRoles, String.class));
userInfo.setSystemId(systemId);
userInfo.setSystemCode(systemCode);
return userInfo;
}
}
```
#### 6.3.3 实现数据隔离
根据请求头中的用户ID和系统ID实现业务数据的隔离
```java
@GetMapping("/list")
public List<BusinessData> getBusinessData(HttpServletRequest request) {
String userId = request.getHeader("X-User-Id");
String systemId = request.getHeader("X-System-Id");
// 根据用户ID和系统ID查询该用户在该系统下的业务数据
return businessDataService.listByUserIdAndSystemId(userId, systemId);
}
```
### 6.4 对接测试步骤
1. 启动网关平台和业务系统
2. 访问业务系统前端地址,验证是否自动跳转到统一登录页
3. 使用测试账号登录,验证是否正确跳转到系统选择页或直接进入业务系统
4. 验证业务系统是否能正确获取用户信息和菜单路由
5. 验证业务系统接口请求是否经过网关转发,后端是否能正确获取请求头中的用户信息
6. 验证未授权接口是否被网关拦截
7. 验证退出登录功能是否正常
### 6.5 常见问题
1. 跨域问题:请在网关服务中配置跨域支持,允许业务系统前端域名访问
2. Token过期请在前端响应拦截器中处理401状态码自动跳转到统一登录页
3. 请求头丢失:请确保网关服务在转发请求时正确保留和注入请求头
4. 动态路由加载失败:请检查网关平台是否正确配置了该系统的菜单和用户权限
---
## 附录:文档审查问题清单
### 🔴 严重不一致(必须修正)
**#1 统一登录域名不一致**
- 第 3.1.1 节:`https://login.user.mokee.com`
- 第 6.2.2 节及后续多处:`https://login.mokeeuserlogin.com`
- 建议统一为:`https://login.user.mokee.com`
**#2 API 路径前缀不一致**
- 第 5.2.1 节接口列表使用:`/zgapi/v1/auth/...`
- 第 6.2.5 节前端示例代码使用:`/api/v1/auth/...`(缺少 `zg` 前缀)
- 建议统一为:`/zgapi/v1/...`
**#3 登录返回数据中的待确认项**
- 第 3.1.3 节返回 JSON 注释:`//还要不要加一个当前选着系统?`"选着"是错别字,应为"选择"
- 需确认:是否需要返回"当前选中系统"信息?
### 🟡 数据表设计问题(建议修正)
**#4 sys_user_role 表冗余字段**
- `sys_user_role` 表有 `system_id` 字段,但 `role_id` 关联的 `sys_role` 表已包含 `system_id` —— 不一致风险
**#5 缺少逻辑删除字段**
- 所有表无 `is_deleted` 字段
**#6 缺少审计字段**
- 所有表缺少 `created_by` / `updated_by`
**#7 sys_role_menu 表缺少时间字段**
- 与其他关联表(`sys_user_system``sys_user_role`)不一致
**#8 sys_user 表缺少字段**
- 缺少 `last_login_ip`
- 密码加密算法未明确BCryptSCrypt
**#9 未定义索引策略**
- 所有表未提及索引设计
### 🟠 功能缺失(建议补充)
**#10 缺少 Token 刷新机制**
**#11 缺少统一登出SSO Logout**
**#12 缺少登录安全措施**
- 无验证码机制
- 无密码复杂度策略
- 无账号锁定策略(多次失败锁定)
- 无限流机制
**#13 缺少跨域CORS配置方案**
**#14 X-User-Roles 请求头格式未明确**
- 数组元素包含哪些字段?
### 🔵 细节问题
**#15 needSelectSystem 字段冗余**
- 前端可通过 `systemList.length > 1` 判断
**#16 前端代码示例问题**
- 路由守卫缺 `async`
- 每次路由切换都读 localStorage性能
**#17 第 3 节与第 6 节内容重叠**