认证与系统基础接口.md 32 KB

认证与系统基础接口

本文引用的文件

  • AuthController.java
  • UserController.java
  • SystemController.java
  • CaseInfoController.java
  • TableInfoController.java
  • TowerController.java
  • SysUserService.java
  • LoginDTO.java
  • OpenCaseDTO.java
  • UpdateCasePwdDTO.java
  • LoginVO.java
  • UserVO.java
  • Result.java
  • AccountInUseException.java
  • GlobalExceptionHandler.java
  • SysUser.java
  • CaseInfo.java
  • TableInfo.java
  • SystemInfo.java
  • authApi.ts
  • account.ts
  • user.sql
  • plat.sql

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细接口说明
  6. 依赖关系分析
  7. 性能与分页特性
  8. 故障排查指南
  9. 结论

简介

本文面向前端和后端维护者,系统性梳理 plat 模块下 /auth、/user、/sys、/case、/tpl、/tower 等控制器的 API 契约。重点包括:

  • 登录流程:前端如何调用 /auth/login 获取 token,后续请求如何携带 x-token,Sa-Token 与会话活跃检测如何配合完成“账号占用确认”“强制登录”“顶下线”。
  • 用户信息、授权单元、系统信息、案件数据源、表模板、塔台基站的 HTTP 方法、URL、请求参数、响应字段、分页格式和错误码。
  • 登录失效、账号被顶下线、管理员重置密码或强制下线时,前端缓存清理和状态恢复行为。
  • curl 与前端调用示例,以及 401、403、503 等错误的排查步骤。

项目结构

plat 模块采用典型的 Spring MVC 分层:控制器负责路由和统一响应包装,服务层封装认证、用户管理、案件、系统和塔台业务,实体类描述数据库模型,DTO/VO 描述接口入参出参。

graph TB
    Client["前端页面<br/>浏览器 / Electron"] --> Gateway["网关 / 反向代理"]
    Gateway --> AuthCtl["/auth 认证控制器"]
    Gateway --> UserCtl["/user 用户管理控制器"]
    Gateway --> SysCtl["/sys 系统控制器"]
    Gateway --> CaseCtl["/case 案件控制器"]
    Gateway --> TplCtl["/tpl 表模板控制器"]
    Gateway --> TowerCtl["/tower 塔台控制器"]

    AuthCtl --> SysSvc["SysUserService<br/>认证 + 用户管理"]
    UserCtl --> SysSvc
    CaseCtl --> CaseSvc["CaseInfoService"]
    TplCtl --> TableSvc["TableInfoService"]
    TowerCtl --> TowerSvc["TowerService"]
    SysCtl --> SystemSvc["SystemService"]
    SysCtl --> HealthSvc["SystemHealthService"]

    SysSvc --> Stp["Sa-Token<br/>会话与 Token"]
    SysSvc --> DsReg["CaseDataSourceRegistry<br/>案件数据源注册表"]
    SysSvc --> Cache["CaseDataCache<br/>案件数据缓存"]

图示来源

  • AuthController.java:1-82
  • UserController.java:1-89
  • SystemController.java:1-200
  • CaseInfoController.java:1-117
  • TableInfoController.java:1-91
  • TowerController.java:1-54
  • SysUserService.java:1-200

章节来源

  • AuthController.java:1-82
  • UserController.java:1-89
  • SystemController.java:1-200
  • CaseInfoController.java:1-117
  • TableInfoController.java:1-91
  • TowerController.java:1-54

核心组件

  • 认证控制器 /auth:提供登录、登出、当前用户信息、修改密码、校验密码。其中 /auth/login 在 Sa-Token 拦截器白名单中,其余接口需要登录。
  • 用户管理控制器 /user:用户分页列表、创建、更新、重置密码、删除、强制下线。所有接口要求当前用户是管理员。
  • 系统控制器 /sys:健康检查、系统服务探测、授权信息、机器码、离线授权激活、缓存清理、升级包上传、文件下载、本地文件打开、离线地图瓦片与样式等。
  • 案件控制器 /case:查询自己的案件列表、新建或更新案件、删除、更新案件密码、开启案件、退出案件、查询当前已打开案件。
  • 表模板控制器 /tpl:模板分页查询、名称重复性检查、分类枚举、详情、创建、更新、删除。
  • 塔台控制器 /tower:基站查询、上传基站 xls/xlsx 转换、下载转换模板。
  • 统一响应体 Result:所有业务接口返回 {code, message, data};成功默认 code 为 200,失败默认 code 为 400。
  • 登录异常 AccountInUseException:账号正在其他设备使用时返回 HTTP 200 + body.code=40901,前端据此弹出是否继续登录的确认框。

章节来源

  • AuthController.java:1-82
  • UserController.java:1-89
  • SystemController.java:1-200
  • CaseInfoController.java:1-117
  • TableInfoController.java:1-91
  • TowerController.java:1-54
  • Result.java:1-114
  • AccountInUseException.java:1-19

架构总览

认证与系统基础接口的关键交互如下:

sequenceDiagram
    participant FE as "前端"
    participant GW as "网关 / 反向代理"
    participant AC as "认证控制器"
    participant SVC as "SysUserService"
    participant ST as "Sa-Token"
    participant ACT as "登录活跃服务"
    participant DS as "案件数据源注册表"
    participant CACHE as "案件数据缓存"

    FE->>GW: POST /auth/login {username,password,force}
    GW->>AC: 转发登录请求
    AC->>SVC: login(LoginDTO)
    SVC->>ACT: isInUse(userId)
    alt 账号正在使用且未 force
        SVC-->>AC: 抛出 AccountInUseException
        AC-->>FE: HTTP 200 {code:40901,message}
        FE->>FE: 弹出确认框
        FE->>GW: POST /auth/login {...,force:true}
        GW->>AC: 转发强制登录
        AC->>SVC: login(force=true)
        SVC->>ST: kickout(userId)
        SVC->>DS: 释放旧会话打开的案件
        SVC->>CACHE: 清理旧会话案件缓存
        SVC->>ST: login(userId)
        SVC-->>AC: LoginVO{token,...}
        AC-->>FE: {code:200,data:LoginVO}
    else 正常登录
        SVC->>ST: login(userId)
        SVC-->>AC: LoginVO{token,...}
        AC-->>FE: {code:200,data:LoginVO}
    end

    Note over FE,GW: 后续请求通过 x-token 携带令牌

图示来源

  • AuthController.java:28-48
  • SysUserService.java:63-118
  • AccountInUseException.java:11-19
  • GlobalExceptionHandler.java:41-52
  • authApi.ts:77-85
  • account.ts:57-65

详细接口说明

认证接口 /auth

HTTP 方法 URL 鉴权 请求体 成功响应 说明
POST /auth/login 无需登录 {username,password,force?} {code:200,data:{token,userId,username,displayName,isAdmin}} 登录;账号被占用且未 force 时返回 HTTP 200 + code=40901
POST /auth/logout 可选(401 也允许) 无 {code:200} 登出并释放该 token 打开的案件
GET /auth/info 需登录 无 {code:200,data:{id,username,displayName,isAdmin,status,createTime,lastLoginTime}} 刷新页面后恢复用户态
POST /auth/changePwd 需登录 {oldPwd,newPwd} {code:200} 自助修改密码
POST /auth/verifyPwd 需登录 {password?} {code:200,data:boolean} 锁屏解锁;密码错返回 false 而非 401

登录请求字段

  • username:登录名,必填。
  • password:明文密码,服务端用 BCrypt 比对,不落库。
  • force:可选布尔值;当账号正在其他设备使用时首次登录返回 40901,用户确认后带 force=true 重新提交以接管旧会话。

登录成功返回字段

  • token:Sa-Token 登录凭据,前端写入缓存后由请求拦截器注入 x-token 请求头。
  • userId:用户 ID。
  • username:登录名。
  • displayName:显示名。
  • isAdmin:1 为管理员,0 为普通用户。

错误行为

  • 用户名或密码为空:HTTP 400 + code=400 + message。
  • 用户名或密码错误:HTTP 400 + code=400 + message。
  • 账号已被停用:HTTP 400 + code=400 + message。
  • 账号正在其他设备使用:HTTP 200 + code=40901 + message,前端弹确认框。

章节来源

  • AuthController.java:28-81
  • LoginDTO.java:1-25
  • LoginVO.java:1-24
  • SysUserService.java:63-118
  • AccountInUseException.java:11-19
  • GlobalExceptionHandler.java:41-52

前端登录调用示例

  • curl
    • 正常登录:curl -X POST http://localhost:端口/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"admin123"}'
    • 强制登录:curl -X POST http://localhost:端口/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"admin123","force":true}'
  • 前端调用
    • 调用 /auth/login,设置 isTransformResponse:false,因为 40901 是正常分支。
    • 成功后从响应体取 data.token,写入 localStorage,并在后续请求中通过 x-token 请求头携带。
    • 若返回 code===40901,弹出“是否确定登录”确认框;确认后再次调用同一接口并传入 force:true。

章节来源

  • authApi.ts:24-30
  • authApi.ts:77-85
  • account.ts:57-65

用户管理接口 /user

HTTP 方法 URL 鉴权 请求体 成功响应 说明
GET /user/list 管理员 keyword?, page?, size? {code:200,data:Page<UserVO>} 按登录名或显示名模糊匹配分页
POST /user/create 管理员 {username,password,displayName?,isAdmin?,status?} {code:200} 新建用户
POST /user/update 管理员 {id,displayName?,isAdmin?,status?} {code:200} 修改显示名、管理员标志、启用状态
POST /user/resetPwd 管理员 {id,newPassword} {code:200} 重置密码并强制该用户下线
POST /user/delete 管理员 {id} {code:200} 删除用户
POST /user/kickout 管理员 {id} {code:200} 强制指定用户下线

分页字段

  • keyword:可选,模糊匹配登录名或显示名。
  • page:可选,默认 1。
  • size:可选,默认 20。
  • 返回的 data 是 MyBatis-Plus Page 对象,包含 current、size、total、records。

用户返回字段

  • id:用户 ID。
  • username:登录名。
  • displayName:显示名。
  • isAdmin:1 为管理员,0 为普通用户。
  • status:1 为启用,0 为停用。
  • createTime:创建时间。
  • lastLoginTime:最后登录时间。

错误行为

  • 非管理员调用:HTTP 403 + code=403 + message。
  • 用户名或新密码为空:HTTP 400 + code=400 + message。
  • 用户不存在:HTTP 400 + code=400 + message。
  • 尝试删除最后一个管理员:HTTP 400 + code=400 + message。
  • 用户名下还有案件:HTTP 400 + code=400 + message。
  • 密码长度少于 6 位:HTTP 400 + code=400 + message。

章节来源

  • UserController.java:18-88
  • SysUserService.java:138-429
  • UserVO.java:1-28
  • SysUser.java:1-61

系统接口 /sys

HTTP 方法 URL 鉴权 请求体 成功响应 说明
GET /sys/health 通常无需登录 无 {code:200} 健康检查
GET /sys/serviceHealth 通常无需登录 无 {code:200,data:[ServiceHealthDTO]} 后端、PostgreSQL、Redis、Elasticsearch 可用性与耗时
GET /sys/info 通常无需登录 无 {code:200,data:SystemInfo} 系统授权信息
GET /sys/code 通常无需登录 无 {code:200,data:string} 服务器机器码
POST /sys/noNet 通常无需登录 multipart/form-data file=.xlts {code:200} 离线授权激活
GET /sys/cleanCache 通常无需登录 无 {code:200} 清理系统缓存
POST /sys/uploadUpgrade 通常无需登录 multipart/form-data file=zip {code:200} 上传升级包并执行升级
GET /sys/downloadFile 通常无需登录 query fid=file_info.id 文件流 按文件 ID 下载附件,不返回 Result
GET /sys/map/pmtiles 通常无需登录 header Range? 瓦片字节流 离线地图 PMTiles,支持 Range
GET /sys/map/style 通常无需登录 无 样式 JSON 或 404 离线地图自定义样式

系统信息字段

  • machinecode:机器码。
  • clientNo:客户编号。
  • unit:单位。
  • phone:手机号。
  • authdatetime:授权时间。
  • overdatetime:过期时间。
  • activeDateTime:激活时间。
  • remainingDate:剩余天数,非数据库字段。

错误行为

  • 健康检查失败或外部服务不可用时,serviceHealth 会返回各服务的探测结果;整体仍可能走 200,但前端应读取 data 中的状态字段判断可用性。
  • 文件下载或离线地图资源缺失时,可能返回 404,前端应按业务逻辑处理回退。

章节来源

  • SystemController.java:1-200
  • SystemInfo.java:1-71
  • plat.sql:1-154

案件接口 /case

HTTP 方法 URL 鉴权 请求体 成功响应 说明
GET /case/list 需登录 无 {code:200,data:[CaseInfo]} 仅返回当前登录用户自己的案件
POST /case/create 需登录 CaseInfo JSON {code:200} 带 id 为更新,不带 id 为新建
GET /case/delete 需登录 query id {code:200} 删除案件
POST /case/updatePwd 需登录 {id,newPwd} {code:200} 更新案件密码
POST /case/open 需登录 {id,pwd?} {code:200,data:CaseInfo} 开启案件,返回工作空间路径
GET /case/exit 需登录 无 {code:200} 退出案件
GET /case/current 需登录 无 `{code:200,data:CaseInfo null}`

案件实体字段

  • id:案件 ID。
  • name:案件名称。
  • pwd:案件密码,写保护,不返回给前端。
  • db:数据库名称,忽略序列化。
  • dbPath:数据库路径,忽略序列化。
  • type:案件类型。
  • remark:备注。
  • createTime:创建时间。
  • init:是否初始化。
  • ownerId:归属用户 ID。
  • workspacePath:工作空间目录,非数据库字段,由服务端补回。

错误行为

  • 未登录:Sa-Token 拦截器统一处理,通常为 401。
  • 参数绑定失败:若前端用表单参数而非 JSON body 调用 create/open/updatePwd,会抛 500。
  • 越权访问他人案件:服务层按 owner_id 隔离,越权请求会被拒绝。

章节来源

  • CaseInfoController.java:18-116
  • CaseInfo.java:1-101
  • OpenCaseDTO.java:1-20
  • UpdateCasePwdDTO.java:1-12
  • user.sql:1-75

表模板接口 /tpl

HTTP 方法 URL 鉴权 请求体 成功响应 说明
GET /tpl/page 需登录 table_name_cn?, has_inner?, classify?, page, limit {code:200,data:Page<TableInfo>} 模板分页查询
GET /tpl/checkName 需登录 old_table_name_cn?, name `{code:200,data:"Y" "N"}`
GET /tpl/cag 需登录 无 {code:200,data:[string]} 分类枚举
GET /tpl/detail 需登录 id {code:200,data:TableInfo} 模板详情
POST /tpl/create 需登录 TableInfo JSON {code:200} 创建模板
POST /tpl/update 需登录 TableInfo JSON {code:200} 更新模板
GET /tpl/delete 需登录 id {code:200} 删除模板

模板分页字段

  • table_name_cn:可选,中文表名模糊匹配。
  • has_inner:可选,1 表示有内嵌,0 表示无内嵌。
  • classify:可选,按类别过滤。
  • page、limit:分页页码与每页条数。

模板实体字段

  • id:主模版 ID。
  • mainId:主模版 ID。
  • tableNameCn:表名中文。
  • tableNameEn:表名英文。
  • headers:表头。
  • classify:类别。
  • hasInner:是否有内嵌。
  • hasTable:是否有表。
  • createTime:创建时间。
  • funcRegx:模板函数正则。
  • lineNo:表头行号。
  • tableFields:表字段,非数据库字段。

错误行为

  • 未登录:401。
  • 权限不足:本项目 /tpl 没有独立权限体系,但受全局登录拦截影响。

章节来源

  • TableInfoController.java:15-90
  • TableInfo.java:1-88
  • plat.sql:1-154

塔台接口 /tower

HTTP 方法 URL 鉴权 请求体 成功响应 说明
GET /tower/qry 需登录 mnc,lac,ci {code:200,data:[string]} 基站查询
POST /tower/covFile 需登录 multipart/form-data file=xls/xlsx 文件流 上传基站 xls 并转换,返回 xlsx 文件流
GET /tower/template 需登录 无 文件流 下载基站转换模板

错误行为

  • 未登录:401。
  • 文件格式错误或模板不匹配:由服务层抛出具体异常,前端按通用错误提示。

章节来源

  • TowerController.java:18-53

依赖关系分析

classDiagram
    class AuthController {
        +login(dto)
        +logout()
        +info()
        +changePwd(dto)
        +verifyPwd(dto)
    }

    class UserController {
        +list(keyword,page,size)
        +create(dto)
        +update(dto)
        +resetPwd(dto)
        +delete(dto)
        +kickout(dto)
    }

    class SystemController {
        +health()
        +serviceHealth()
        +info()
        +machineCode()
        +noNet(file)
        +cleanCache()
        +uploadUpgrade(file)
        +downloadFile(fid)
        +mapPmtiles(range)
        +mapStyle()
    }

    class CaseInfoController {
        +list()
        +create(caseInfo)
        +delete(id)
        +updatePwd(dto)
        +open(dto)
        +exit()
        +current()
    }

    class TableInfoController {
        +page(query)
        +checkName(old,name)
        +cag()
        +detail(id)
        +create(tableInfo)
        +update(tableInfo)
        +delete(id)
    }

    class TowerController {
        +qry(mnc,lac,ci)
        +covFile(file)
        +template()
    }

    class SysUserService {
        +login(dto)
        +logout()
        +info()
        +changePwd(dto)
        +verifyPwd(password)
        +list(keyword,page,size)
        +create(dto)
        +update(dto)
        +resetPwd(dto)
        +delete(id)
        +kickout(id)
    }

    AuthController --> SysUserService : "依赖"
    UserController --> SysUserService : "依赖"
    CaseInfoController --> CaseInfoService : "依赖"
    TableInfoController --> TableInfoService : "依赖"
    TowerController --> TowerService : "依赖"
    SystemController --> SystemService : "依赖"
    SystemController --> SystemHealthService : "依赖"

图示来源

  • AuthController.java:1-82
  • UserController.java:1-89
  • SystemController.java:1-200
  • CaseInfoController.java:1-117
  • TableInfoController.java:1-91
  • TowerController.java:1-54
  • SysUserService.java:1-200

章节来源

  • AuthController.java:1-82
  • UserController.java:1-89
  • SystemController.java:1-200
  • CaseInfoController.java:1-117
  • TableInfoController.java:1-91
  • TowerController.java:1-54
  • SysUserService.java:1-200

性能与分页特性

  • 用户列表分页使用 MyBatis-Plus Page,默认 page=1、size=20;返回对象包含 current、size、total、records。
  • 表模板分页由 TableInfoQuery 承载 page 和 limit,同样返回 MyBatis-Plus Page。
  • 登出时会关闭当前 token 打开的案件数据源,避免反复登录登出累积 DuckDB 实例占用内存预算。
  • 管理员禁用用户、重置密码、删除用户或强制下线时,会调用 StpUtil.kickout 并释放对应用户的案件数据源及缓存。
  • 系统升级接口 /sys/uploadUpgrade 会执行版本校验、解压、覆盖数据库、执行升级 SQL,属于长耗时操作,前端应提供进度或超时提示。

章节来源

  • SysUserService.java:118-200
  • SysUserService.java:201-429
  • TableInfoController.java:23-34

故障排查指南

登录相关

  • 401 未登录
    • 原因:Sa-Token 检测到 token 无效、过期或被替换。
    • 排查:检查请求是否携带 x-token;检查前端是否在登录成功后写入 token;检查网关是否正确透传请求头。
    • 处理:清空前端登录缓存,跳转到登录页重新登录。
  • 40901 账号正在使用
    • 原因:该账号存在有效会话且半小时内活跃过。
    • 排查:查看后端日志是否打印“登录被拦截(账号正在使用)”。
    • 处理:前端弹出确认框;用户确认后带 force=true 重新提交;服务端踢掉旧会话并让新会话登录。
  • 400 用户名或密码错误
    • 原因:用户名或密码为空、用户名不存在、密码不匹配、账号停用。
    • 排查:检查请求体是否为 JSON,字段名是否正确。
    • 处理:提示用户重试或联系管理员启用账号。

章节来源

  • AccountInUseException.java:11-19
  • GlobalExceptionHandler.java:41-52
  • SysUserService.java:63-118

权限相关

  • 403 无权限
    • 原因:调用 /user/** 的用户不是管理员。
    • 排查:检查当前登录用户 isAdmin 是否为 1;检查前端是否误把普通用户引导到用户管理入口。
    • 处理:切换到管理员账号或移除普通用户对用户管理的访问。

章节来源

  • SysUserService.java:389-398
  • UserController.java:18-88

系统与服务

  • 503 或服务不可用
    • 原因:网关不可达、后端进程未启动、数据库或 Redis/Elasticsearch 不可用。
    • 排查:先调 /sys/health;再调 /sys/serviceHealth 查看各子服务状态;检查部署环境配置。
    • 处理:重启后端服务、修复数据库连接、检查网关路由。
  • 404 文件下载或地图样式缺失
    • 原因:文件 ID 不存在、离线地图样式未配置。
    • 排查:确认 fid 是否正确;检查系统配置的离线地图目录是否存在样式文件。
    • 处理:前端回退到内置样式或提示资源缺失。

章节来源

  • SystemController.java:1-200

登录失效与缓存清理

  • 登录失效
    • 现象:后续请求返回 401。
    • 前端行为:清除 localStorage 中的 token、用户信息、当前案件缓存,跳转到登录页。
  • 账号被顶下线
    • 触发条件:生产默认单端登录;新登录会替换旧 token。
    • 后端行为:旧 token 下次请求抛未登录异常;若因强制登录接管,旧会话打开的案件会被释放。
    • 前端行为:收到 401 后清理缓存并提示重新登录。
  • 管理员重置密码或强制下线
    • 后端行为:调用 StpUtil.kickout,释放该用户打开的案件数据源和缓存。
    • 前端行为:后续请求 401,清理缓存并跳转登录。

章节来源

  • SysUserService.java:118-200
  • SysUserService.java:201-429
  • GlobalExceptionHandler.java:54-70

结论

plat 模块的认证与系统基础接口以 Sa-Token 为核心,结合登录活跃检测实现“账号占用确认”和“强制登录”,并通过 x-token 请求头维持会话。用户管理接口仅限管理员,案件接口按 owner_id 隔离,表模板和塔台接口分别承担数据建模与基站处理能力。前端应在登录后持久化 token,在 401、403、40901 等场景下正确处理缓存清理和用户引导。运维侧可通过 /sys/health 和 /sys/serviceHealth 快速定位后端及依赖服务状态。