← 返回首页系统设计方案使用说明状态与流程OAuth 对接计划未来功能计划

工单中心 × OAuth2.0 认证中心对接计划

2026-10-15 认证中心重构说明:oauth 已从 plugin/oauth 插件形态重构为自有 webman 项目(app/ 下 admin/index/store 三应用,config/route.php 集中路由)。端点为无前缀:POST /token、GET /userinfo、GET /user-permissions、GET /login;平台管理后台入口 http://127.0.0.1:8788/admin(RBAC 权限管理:/admin/api/clients、/admin/api/permissions、/admin/api/roles、/admin/api/user-roles/set)。工单中心已按此适配(config/app.php 的 oauth.base_url + OAuthClient 路径)。
woc 应用:client_id woc,secret 79220b54d91d7753af40f2de4f7cbf289ab2c49375083a3a(grant_types: password/refresh_token/client_credentials)。
目标:工单中心后台(/console、/api/*)当前无登录与权限控制,需统一走公司 OAuth2.0 认证中心(/Users/body/ai_code/oauth)登录,并按角色做权限判断。

一、OAuth 认证中心能力分析(调研结论)

1.1 部署形态

项 结论 证据
服务 独立 webman 项目,默认监听 8788,可 OAUTH_LISTEN_PORT 覆盖 config/process.php、README
插件形态 自有 webman 项目(app/ 下 admin/index/store 三应用 + config/route.php 集中路由);作为独立服务被 HTTP 调用 composer.json、plugin/oauth/app/service/Database.php
数据库 SQLite 默认(runtime/oauth.db)/MySQL 可切换;模型固定使用名为 oauth 的连接 config/database.php、Database.php:16-40
用户表 user_provider.table 默认指向宿主 users 表(复用不覆盖,幂等补列) config/oauth.php

1.2 登录与令牌

能力 说明
登录页 GET/POST /login(username/password/_csrf_token),支持 ?redirect= 站内回跳,登录成功重建 session ID
授权模式 授权码、密码(password)、客户端凭证(client_credentials)、刷新(refresh_token)、权限刷新(refresh_permissions)、权限验证(access_permissions)
令牌端点 POST /token;client 认证支持表单参数或 HTTP Basic
令牌 TTL access_token 7200s / refresh_token 2592000s / auth_code 600s
用户信息 GET /userinfo(Bearer)、GET /user-permissions(Bearer,含角色+权限码+权限树)
远程权限校验 grant_type=access_permissions:传 client_id+client_secret+access_token+client_permission → 返回 {allowed: true/false}
登录防爆破 LoginGuard:连续失败 5 次锁 15 分钟(按 IP/账号)

1.3 用户/角色/权限模型

表 关键字段 说明
users(宿主) id, username, nickname, email, mobile, password(bcrypt), store_id, enabled 资源所有者(前台登录用户)
oauth_clients client_id(唯一), client_secret, redirect_uris, scopes, grant_types, max_tokens_per_user 应用(每个业务系统一个)
oauth_permissions client_id, parent_id, code(权限码), type(dir/menu/action) 权限节点树,按 client 隔离
oauth_roles client_id, code, parent_id 角色,按 client 隔离,子角色继承父角色
oauth_user_roles user_id, role_id 用户-角色关联
oauth_role_permissions role_id, permission_id 角色-权限关联

1.4 权限判断机制


二、对接方案选型

2.1 集成方式:独立服务 HTTP 调用(推荐) vs 插件拷贝

维度 A. 独立服务 HTTP 调用 B. 插件拷贝进 lb_tips
认证中心单一实例 ✅ 全公司共用一台 ❌ 每项目一份,数据分裂
代码维护 ✅ 只维护 oauth 一处 ❌ 两处同步升级
实现成本 中(写 OAuthClient 服务 + 中间件) 低(直接复用中间件)
端口/部署耦合 低(仅配置 base_url) 高(lb_tips 也开 8788)

决策:方案 A(独立服务 HTTP 调用)。oauth 是公司级认证中心,应保持单一实例;工单中心仅作为它的一个 client(client_id=woc)接入,符合其「第三方接入文档」标准做法。

2.2 登录方式:授权码模式 vs 密码模式

维度 授权码模式 密码模式(password grant)
登录页归属 oauth 的 /login(样式不可定制为 TicketHub 风格) 工单中心自建 TicketHub 风格登录页
安全 最高(标准 OAuth 网页流程) 受信任内部客户端可接受;client_secret 存服务端
工单中心登录页 仅「跳转 oauth 登录」入口页 完整自建表单(用户要求"新增登录页")
复杂度 需回调 + state 校验 仅调 token 端点

决策:密码模式 + 自建登录页。用户明确要求"新增一个登录页",且工单中心是内部系统(受信任客户端),password grant 满足需求且体验统一。client_secret 仅存工单中心服务端配置,不暴露前端。

2.3 权限判断:oauth RBAC 权限码 vs 本地角色

维度 oauth RBAC 权限码 本地角色(users.role)
权限粒度 接口级权限码(workorder:create 等) 角色级(cs/ops/admin)粗粒度
配置位置 oauth 后台(每 client 独立权限树+角色) 工单中心 users 表
实现成本 高(需建权限节点树、角色、用户分配) 低(已存在 role 字段)
可扩展 强 弱

决策:一期本地角色(users.role),二期接入 oauth RBAC 权限码。一期快速闭环:登录时从 oauth 拿用户身份,工单中心本地 users.role 判断权限;二期在 oauth 后台为 woc 配置权限节点树+角色,改为 access_permissions 远程校验。


三、总体架构

┌─────────────────────────────┐        ┌──────────────────────────────┐
│  工单中心 (lb_tips, 8787)    │  HTTP  │  OAuth2.0 认证中心 (8788)     │
│                             │  ────▶ │  POST /token (password)      │
│  /login 自建登录页           │        │  GET  /userinfo                       │
│    ↓ 用户名/密码             │  ◀──── │  (校验成功后)               │
│  AuthController             │        │  用户表 users (username/     │
│    ↓ 换 access_token        │        │  password/enabled)           │
│    ↓ 取 userinfo (user_id)  │        └──────────────────────────────┘
│    ↓ 查本地 users.role      │
│  Session 写入登录态          │
│    ↓                        │
│  AuthMiddleware 校验 Session │
│  /console + /api/* 权限判断  │
└─────────────────────────────┘

四、数据模型调整(工单中心侧)

4.1 users 表补列(tools/migrate.php)

工单中心 users 表补充字段,与 oauth 用户建立关联:

新字段 类型 说明
oauth_user_id bigint nullable 唯一 oauth 认证中心返回的用户主键
username varchar(100) nullable 唯一 oauth 登录用户名(便于运维对应)
password varchar(255) nullable 密码哈希(password_hash/bcrypt,与 oauth 同算法)
说明:同一账号在两处各自建号(oauth 管身份、工单中心管业务档案),通过 oauth_user_id 关联;密码仅用于本地直连 SQLite 开发环境校验(可选),生产统一走 oauth 校验。

4.2 新增表:oauth_clients_meta(可选)

记录工单中心已注册的 oauth client 信息(client_id/client_secret/base_url),或直接用环境变量/config/app.php 配置,不建表。


五、实现步骤

M1:登录闭环(Session 会话 + 本地角色权限)

# 内容 文件
1 新增 OAuthClient 服务:封装 tokenPassword()、userinfo()、refreshToken()、accessPermissionCheck() app/service/OAuthClient.php
2 新增 AuthController:GET /login(渲染登录页)、POST /login(调 oauth password grant → userinfo → 查本地 users.role → 写 Session)、GET /logout app/controller/AuthController.php
3 新增 AuthMiddleware:校验 Session 登录态,未登录跳 /login;从 Session 读 role 挂到 request->user app/middleware/AuthMiddleware.php
4 新增登录页 login.html(TicketHub 设计风格,含用户名/密码/错误提示) public/login.html
5 注册路由:/login、/logout;/console、/api/*、/admin/* 挂 AuthMiddleware config/route.php
6 权限:按 users.role 控制(客服=建单/分派/关闭;客服主管=+取消审批/报表;运维=+接单/处理/回填;管理员=+系统配置/报表) app/controller/*
7 配置:config/app.php 或 .env 增加 OAUTH_BASE_URL / OAUTH_CLIENT_ID / OAUTH_CLIENT_SECRET config/app.php
8 前端适配:console.html 顶部显示登录用户名+角色;侧栏按角色显隐菜单 public/console.html、assets/console.js

M2:令牌生命周期

M3:二期能力(RBAC 权限码已完成 ✅)


六、验证

# 场景 预期
1 未登录访问 /console、/api/work-orders 302 → /login
2 登录页提交 demo/123456(oauth 用户) 登录成功 → /console,顶部显示用户名+角色
3 登录页提交错误密码 明确错误提示;连续 5 次失败 oauth 侧锁定
4 各角色访问权限外接口 403(如 ops 访问 /admin/sla-config)
5 令牌过期 自动刷新,用户无感
6 登出后再次访问受保护页 需重新登录
7 oauth 服务不可达 登录页提示"认证服务不可用"

七、前置条件与风险

项 状态
oauth 服务运行中(8788)且 woc client 已注册(grant_types 含 password) 需运维/管理员操作
users 表需补 oauth_user_id/username/password 列 需执行迁移
工单中心与 oauth 的账号映射(现有 users 记录如何对到 oauth 账号) 需确认:name 与 oauth username 是否一致,或手动建档
本地开发环境无独立 oauth 服务时 可用 oauth 项目的 SQLite 库 demo/123456 直连校验(password 存本地 users 表,同 bcrypt 算法)

附录:关键接口速查

方法 路径 参数 返回
POST /token grant_type=password, client_id, client_secret, username, password access_token, refresh_token, expires_in
POST /token grant_type=refresh_token, client_id, client_secret, refresh_token 新 access/refresh token
GET /userinfo Authorization: Bearer <token> user(id/username/nickname), scope
GET /user-permissions Bearer user, roles, permissions, nodes
POST /token grant_type=access_permissions, client_id, client_secret, access_token, client_permission allowed: true/false