初始化
This commit is contained in:
754
统一登录网关平台-需求文档.md
Normal file
754
统一登录网关平台-需求文档.md
Normal file
@@ -0,0 +1,754 @@
|
||||
# 统一登录网关平台
|
||||
|
||||
## 一、项目概述
|
||||
|
||||
### 1.1 项目背景
|
||||
当前存在多个独立业务系统,各系统均有独立的登录模块、用户体系和权限管理,导致用户需要记忆多套账号密码,管理员需要在多个系统中重复维护用户信息,权限管理混乱且难以统一管控。
|
||||
|
||||
### 1.2 项目目标
|
||||
构建一个统一的多系统登录与权限网关平台,实现:
|
||||
- 统一登录入口:所有业务系统共用一个登录页面(https://login.user.mokee.com),用户一次登录即可访问所有授权系统
|
||||
- 统一用户管理:所有用户信息集中在网关平台维护,业务系统不再存储用户数据
|
||||
- 统一权限管理:所有业务系统的菜单、角色、权限集中在网关平台配置
|
||||
- 统一接口转发:所有业务系统的接口请求统一经过网关转发,网关负责身份认证和用户信息透传
|
||||
- 可配置化接入:新增业务系统无需修改网关代码,仅需在后台配置系统信息即可快速接入
|
||||
- 智能系统跳转:登录成功后自动判断用户绑定系统数量,多系统展示选择页,单系统直接跳转
|
||||
|
||||
### 1.3 核心价值
|
||||
- 提升用户体验:用户无需记忆多套账号密码,一次登录即可访问所有授权系统
|
||||
- 降低管理成本:管理员只需在一个平台维护用户和权限信息
|
||||
- 提高系统安全性:统一身份认证和接口鉴权,避免非法访问
|
||||
- 便于系统扩展:新增业务系统可快速接入,无需重复开发登录和权限模块
|
||||
|
||||
---
|
||||
|
||||
## 二、技术架构
|
||||
|
||||
### 2.1 整体架构图
|
||||
```
|
||||
[用户浏览器]
|
||||
↓
|
||||
[业务系统前端] → [统一登录页面(https://login.user.zgitm.com)]
|
||||
↓
|
||||
[网关服务(9000)] → [认证用户服务(9001)]
|
||||
↓ ↓
|
||||
[业务系统后端] ← [业务管理服务(9002)]
|
||||
↓
|
||||
[MySQL数据库] ← [Redis缓存]
|
||||
```
|
||||
|
||||
### 2.2 微服务拆分与职责
|
||||
|
||||
#### 2.2.1 网关服务(mokee-gateway-gateway)- 端口9000
|
||||
- 统一入口:所有业务系统的接口请求和页面访问统一经过网关
|
||||
- 路由转发:根据配置的系统信息,将请求转发到对应的业务系统后端
|
||||
- 身份认证:校验请求中的Token有效性,拦截未登录请求
|
||||
- 信息透传:将用户ID、用户名、角色、岗位、系统ID等信息注入请求头,传递给业务系统后端
|
||||
- 接口鉴权:校验请求接口是否在业务系统的放行列表中
|
||||
|
||||
#### 2.2.2 认证用户服务(mokee-gateway-auth)- 端口9001
|
||||
- 登录认证:处理用户登录请求,验证账号密码,生成Token
|
||||
- 用户管理:维护用户基本信息、用户与系统的绑定关系
|
||||
- 权限管理:维护角色、菜单信息,用户与角色的绑定关系
|
||||
- 会话管理:管理Redis中的用户登录会话,处理退出登录请求
|
||||
- 基础接口:提供获取用户信息、系统信息、菜单路由等基础接口
|
||||
- 系统选择:登录成功后判断用户绑定系统数量,返回系统列表或直接跳转
|
||||
|
||||
#### 2.2.3 业务管理服务(mokee-gateway-admin)- 端口9002
|
||||
- 系统管理:维护业务系统的基本信息、域名配置、接口放行列表
|
||||
- 数据字典:维护全局通用的数据字典
|
||||
- 日志管理:记录用户登录日志和系统操作日志
|
||||
- 定时任务:执行系统定时任务,如自动锁定长期未登录用户
|
||||
|
||||
### 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 | 当前登录用户的唯一ID(UUID) |
|
||||
| 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) | 是 | 系统ID(UUID) |
|
||||
| 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) | 是 | 接口ID(UUID) |
|
||||
| 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) | 是 | 用户ID(UUID) |
|
||||
| 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) | 是 | 关联ID(UUID) |
|
||||
| user_id | varchar(36) | 否 | 用户ID |
|
||||
| system_id | varchar(36) | 否 | 系统ID |
|
||||
| create_time | datetime | 否 | 绑定时间 |
|
||||
|
||||
#### 4.1.5 角色表(sys_role)
|
||||
| 字段名 | 数据类型 | 主键 | 说明 |
|
||||
|-------|---------|------|------|
|
||||
| role_id | varchar(36) | 是 | 角色ID(UUID) |
|
||||
| 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) | 是 | 关联ID(UUID) |
|
||||
| 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) | 是 | 菜单ID(UUID) |
|
||||
| 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) | 是 | 关联ID(UUID) |
|
||||
| role_id | varchar(36) | 否 | 角色ID |
|
||||
| menu_id | varchar(36) | 否 | 菜单ID |
|
||||
|
||||
#### 4.1.9 登录日志表(sys_login_log)
|
||||
| 字段名 | 数据类型 | 主键 | 说明 |
|
||||
|-------|---------|------|------|
|
||||
| log_id | varchar(36) | 是 | 日志ID(UUID) |
|
||||
| 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) | 是 | 日志ID(UUID) |
|
||||
| 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`
|
||||
- 密码加密算法未明确(BCrypt?SCrypt?)
|
||||
|
||||
**#9 未定义索引策略**
|
||||
- 所有表未提及索引设计
|
||||
|
||||
### 🟠 功能缺失(建议补充)
|
||||
|
||||
**#10 缺少 Token 刷新机制**
|
||||
|
||||
**#11 缺少统一登出(SSO Logout)**
|
||||
|
||||
**#12 缺少登录安全措施**
|
||||
- 无验证码机制
|
||||
- 无密码复杂度策略
|
||||
- 无账号锁定策略(多次失败锁定)
|
||||
- 无限流机制
|
||||
|
||||
**#13 缺少跨域(CORS)配置方案**
|
||||
|
||||
**#14 X-User-Roles 请求头格式未明确**
|
||||
- 数组元素包含哪些字段?
|
||||
|
||||
### 🔵 细节问题
|
||||
|
||||
**#15 needSelectSystem 字段冗余**
|
||||
- 前端可通过 `systemList.length > 1` 判断
|
||||
|
||||
**#16 前端代码示例问题**
|
||||
- 路由守卫缺 `async`
|
||||
- 每次路由切换都读 localStorage(性能)
|
||||
|
||||
**#17 第 3 节与第 6 节内容重叠**
|
||||
Reference in New Issue
Block a user