无尘阁日记

无尘阁日记

跟三方OA对接鉴权设计
2026-03-13

我问:

获取token 地址:/api/oauth/getTokenBySso

参数说明

下列参数格式加密后的字段

参数名

参数值

必选

类型

说明


encryption

xxx

string

jwt加密字段


字段名 值 说明

thirdparty zhipingyun 调用来源

module CLOUD 模式:CLOUD/SELFBUILT,请求方为云模式或者自建模式

tenantId A1 企业组织码

creditCode 913xxxxxxxxxxxxxxx 企业信用代码

expireTime 1770000000 过期时间

nonce 8f3c5a7d2b9e41 随机码

{

  "thirdparty": "zhipingyun",

  "module":"cloud",

  "tenantId": "A1",

  "creditCode": "913xxxxxxxxxxxxxxx",

  "expireTime": 1770000000,

  "nonce": "8f3c5a7d2b9e41..."

}


校验接口

获取token 地址:/api/oauth/verify

参数名


参数值


必选


类型


说明



encryption


xxx



string


请求token时携带的加密字段



最后定下来的接口设计如上。

流程如下:

目的

实现自动化对接获取对方各自的token,完成自动一体化集成,客户在打通诺明/智评云过程中,最大幅度减少手动的配置项。


诺明     智评云

 tenant A1  <-----> tenante B1

通过 统一社会信用代码 可关联租户关系



统一社会信用代码属于公开可查询,单纯使用则会导致凭证泄漏隐患


 SSO Token Exchange + 第三方签名验证方案

常规oauth2.0 需要客户端(资源调用者) 储存认证端的认证信息,难以满足一体化集成

诺明获取智评云token步骤


诺明系统 -> 智评云

   |

   | jwt(诺明租户ID+统一社会信用代码+expireTime过期时间+nonce)

   v

智评云解密校验

   |

   | 调用诺明 verify接口,验证签名是否出自服务端颁发

   v

诺明验证

   |

   v

智评云颁发token

--------------------


智评云获取诺明token步骤


智评云 ->诺明系统

   |

   | jwt(智评云租户ID+统一社会信用代码+expireTime过期时间+nonce)

   v

诺明系统解密校验

   |

   | 调用智评云 verify接口,验证签名是否出自服务端颁发

   v

智评云验证

   |

   v

诺明颁发token



1. 诺明请求智评云token获取接口xxx/getTokenBySso

POST xxx/getTokenBySso


body:

signature:jwt(诺明租户ID+统一社会信用代码+expireTime过期时间+nonce)


2. 智评云响应后,解析出诺明租户ID+统一社会信用代码+expireTime过期时间,并进行相关校验(统一社会信用代码对应租户验证、过期时间验证)


3. 初步验证通过后,服务端post请求诺明第三方票据校验接口

POST xxx/verify


body:

thirdparty:zhipingyun

signature:诺明signature


3. 诺明会解密签名和对应第三方系统,缓存验证签名是否存在,验证通过则说明此签名是诺明服务端颁发,如果不存在,即使加密方式泄漏,也可防伪造,返回信息

{

  "success":"true"

}



// 失败返回

{

  "success":false,

   "error": [

        {

            "type": "",

            "msg": "失败原因"

        }

    ]

}

4. 智评云解析响应信息,成功则颁发token


解决问题:

1.  不需要双方长期保存client_secret

采用双方约定的jwt加密方式+签名验证较短过期时间,防止敏感数据交互,采用服务端二次验证,防止伪造


自建客户问题

自建客户请求的地址和校验都是自身的,所以自建客户的获取token和验证接口,需要双方配置才行

自建配置解析

双方自建需要在请求获取token前,解析出统一社会信用代码对应的获取baseurl

sso_baseurl=https:zhipingyun.com


流程是:

对方请求我们,带着加密的encryption,我们直接拿着这个encryption请求他们的verify验证是他们颁发的,验证通过,我们接着解密并存下这个encryption,执行日志记录啊,跟这个encryption里的信用代码关联。请你对我已经设计完的几个表做一下重新设计。


-- =========================================================

-- 说明:

-- 基于你前面刚补充的新通信方式,原先“app_key + app_secret 登录换 token”的模型已经不再适合作为核心认证模型,

-- 现在改为:

--

-- 1)通过统一社会信用代码关联租户关系

-- 2)请求方向目标系统申请 token 时,不再直接提交 app_key / app_secret

-- 3)而是提交一段由发起方服务端签发的 JWT

-- 4)JWT 内至少包含:

--    - 发起方租户ID(partner_tenant_id)

--    - 企业统一社会信用代码(enterprise_code)

--    - expire_time(过期时间)

--    - nonce(随机串,防重放)

-- 5)目标系统收到 JWT 后:

--    - 先做基础解析与时效校验

--    - 再调用发起方 verify 接口,验证该 JWT/签名是否确实由对方服务端签发

--    - 验证通过后,目标系统再签发自己的 access_token

--

-- 因此表结构也要随之调整:

-- 1)去掉以 app_key/app_secret 为中心的认证主模型

-- 2)强化 partner 主配置、verify 接口配置、连通性快照

-- 3)强化 SSO/JWT 换 token 主日志

-- 4)强化 verify 调用明细日志

-- 5)access_token 的签发、失效、吊销保留独立日志,便于后续审计、排障、统计

--

-- 设计原则:

-- 1)一个 partner 仍等于一家企业,但表名/字段名继续保留 partner,便于对外沟通

-- 2)tenant_id 仍是我们系统中的企业唯一编码

-- 3)enterprise_code 存统一社会信用代码,用来建立双方企业映射关系

-- 4)适度冗余关键字段,方便日志自解释,避免完全依赖主表追溯

-- 5)必要日志必须可追踪、可审计、可排障,但不过度堆字段

-- =========================================================


-- =========================================================

-- 对接企业主表

--

-- 用途:

-- 1)记录“一个 partner 就是一家企业”的主配置

-- 2)保存与新 SSO/JWT 通信方式有关的核心配置

-- 3)保存当前最新连通性快照

--

-- 这里不再以 app_key / app_secret 作为核心字段

-- 因为新方案的核心是:

-- “发起方服务端签发 JWT -> 目标系统调用发起方 verify 接口核验 -> 目标系统签发 access_token”

-- =========================================================

DROP TABLE IF EXISTS `bridge_partner`;

CREATE TABLE `bridge_partner`

(

    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',


    `tenant_id`                       BIGINT NOT NULL COMMENT '我们系统中的企业唯一编码。你已明确:tenant_id 实际就是企业ID',

    `enterprise_code`                 VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码。双方租户关系的核心匹配字段之一',

    `partner_code`                    VARCHAR(100) NOT NULL COMMENT '对接企业编码。虽然一个partner本质上等于一家企业,但仍保留该叫法,便于和领导、业务、接口文档持续沟通,例如 nuoming',

    `partner_name`                    VARCHAR(255) NOT NULL COMMENT '对接企业名称',

    `enterprise_name`                 VARCHAR(255) DEFAULT NULL COMMENT '企业名称冗余字段,便于查询、展示、日志排查',


    `partner_effective_time`          DATETIME DEFAULT NULL COMMENT '企业对接生效时间。为空表示不限制起始时间',

    `partner_expire_time`             DATETIME DEFAULT NULL COMMENT '企业对接失效时间。超过该时间后,不允许再进行JWT换token、业务调用等动作',


    `api_host_test`                   VARCHAR(500) DEFAULT NULL COMMENT '对方测试环境基础地址,例如 https://test.xxx.com',

    `api_host_production`             VARCHAR(500) DEFAULT NULL COMMENT '对方正式环境基础地址,例如 https://api.xxx.com',


    `verify_path`                     VARCHAR(500) DEFAULT NULL COMMENT '对方用于“验证JWT是否由其服务端签发”的 verify 接口路径。建议只存相对路径,如 /open-api/sso/verify,实际调用时再按环境拼接host',

    `verify_http_method`              VARCHAR(20) NOT NULL DEFAULT 'POST' COMMENT 'verify接口请求方式,通常为POST',

    `verify_timeout_ms`               INT NOT NULL DEFAULT 5000 COMMENT '调用对方verify接口的超时时间,单位毫秒',

    `verify_retry_count`              INT NOT NULL DEFAULT 0 COMMENT 'verify接口失败后的最大重试次数。0表示失败后不重试',

    `verify_retry_interval_ms`        INT NOT NULL DEFAULT 0 COMMENT 'verify接口重试间隔,单位毫秒。只有 verify_retry_count > 0 时才有意义',


    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '约定的JWT算法标识,例如 HS256、RS256。该字段主要用于协议记录和基础校验,不代表一定在本地完成完整签名验签',

    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '约定的JWT签发者issuer。若协议里要求校验iss,可在基础校验时使用',

    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '约定的JWT受众audience。若协议里要求校验aud,可在基础校验时使用',

    `jwt_max_valid_seconds`           INT NOT NULL DEFAULT 300 COMMENT '发起方JWT允许的最大有效期秒数。用于防止对方签发一个过长生命周期的JWT',

    `allowed_clock_skew_seconds`      INT NOT NULL DEFAULT 300 COMMENT '服务端允许的时钟偏差秒数。用于处理双方服务器时间略有误差的情况',

    `nonce_expire_seconds`            INT NOT NULL DEFAULT 600 COMMENT 'nonce防重放有效窗口,单位秒。超过该窗口的请求即便JWT未彻底过期,也可视业务拒绝',

    `token_expire_seconds`            INT NOT NULL DEFAULT 7200 COMMENT '我方在verify通过后签发给对方的 access_token 默认有效期,单位秒',

    `ip_allow_list`                   VARCHAR(2000) DEFAULT NULL COMMENT '来源IP白名单,多个以英文逗号分隔。为空表示不限制。用于限制谁可以调用JWT换token接口',

    `status`                          TINYINT NOT NULL DEFAULT 1 COMMENT '记录状态:0-停用,1-启用。停用后不允许JWT换token、不允许业务接口交互',


    `oa_connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '当前最新连通状态快照:0-未测试,1-成功,2-失败',

    `oa_connect_env`                  VARCHAR(20) DEFAULT NULL COMMENT '最近一次测试环境:TEST/PRODUCTION',

    `oa_connect_test_type`            VARCHAR(30) DEFAULT NULL COMMENT '最近一次测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token链路测试',

    `oa_connect_time`                 DATETIME DEFAULT NULL COMMENT '最近一次点击“连通对方OA”或系统自动探测的时间',

    `oa_connect_result_code`          VARCHAR(64) DEFAULT NULL COMMENT '最近一次连通测试结果码,如 SUCCESS/TIMEOUT/DNS_ERROR/HTTP_403/HTTP_500/VERIFY_FAIL 等',

    `oa_connect_result_msg`           VARCHAR(1000) DEFAULT NULL COMMENT '最近一次连通测试结果说明',

    `oa_connect_response_time_ms`     INT DEFAULT NULL COMMENT '最近一次连通测试总耗时,单位毫秒',

    `oa_connect_by`                   BIGINT DEFAULT NULL COMMENT '最近一次执行连通测试的操作人。若为系统自动任务,可为空或写系统用户ID',


    `remark`                          VARCHAR(1000) DEFAULT NULL COMMENT '备注,可记录该企业的特殊对接说明',

    `created_by`                      BIGINT DEFAULT NULL COMMENT '创建人',

    `updated_by`                      BIGINT DEFAULT NULL COMMENT '更新人',

    `is_deleted`                      TINYINT NOT NULL DEFAULT 0 COMMENT '是否逻辑删除:0否,1是',

    `deleted_time`                    DATETIME DEFAULT NULL COMMENT '逻辑删除时间',

    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`) USING BTREE,

    UNIQUE KEY `uk_tenant_id` (`tenant_id`) USING BTREE,

    UNIQUE KEY `uk_partner_code` (`partner_code`) USING BTREE,

    UNIQUE KEY `uk_enterprise_code` (`enterprise_code`) USING BTREE,


    KEY `idx_partner_name` (`partner_name`) USING BTREE,

    KEY `idx_status` (`status`) USING BTREE,

    KEY `idx_partner_expire_time` (`partner_expire_time`) USING BTREE,

    KEY `idx_oa_connect_status` (`oa_connect_status`) USING BTREE

) ENGINE=InnoDB

  DEFAULT CHARSET=utf8mb4

  COLLATE=utf8mb4_0900_ai_ci COMMENT='对接企业主表(新SSO/JWT模式主配置表,一个partner即一家企业)';



-- =========================================================

-- 对方OA / verify接口 连通性测试日志表

--

-- 用途:

-- 1)记录每次点击“连通对方OA”的完整历史

-- 2)记录测试的是基础地址、verify接口,还是完整换token链路

-- 3)记录失败原因、HTTP状态、响应耗时、操作人

--

-- 说明:

-- bridge_partner 上只保留“最新快照”

-- 本表保留“全量历史”

-- =========================================================

DROP TABLE IF EXISTS `bridge_partner_connectivity_log`;

CREATE TABLE `bridge_partner_connectivity_log`

(

    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',

    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码,冗余保存便于按信用代码排查',

    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',


    `connect_env`                  VARCHAR(20) NOT NULL COMMENT '测试环境:TEST/PRODUCTION',

    `test_type`                    VARCHAR(30) NOT NULL COMMENT '测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token测试',

    `target_host`                  VARCHAR(500) DEFAULT NULL COMMENT '本次测试命中的host,例如测试环境或正式环境基础地址',

    `target_path`                  VARCHAR(500) DEFAULT NULL COMMENT '本次测试命中的接口路径。例如 verify_path 或 token exchange path',

    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次实际请求的完整URL,便于日志直接排查',

    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,例如 GET/POST',

    `connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '测试结果:0-失败,1-成功',

    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '结果码:SUCCESS/TIMEOUT/DNS_ERROR/SSL_ERROR/HTTP_401/HTTP_403/HTTP_404/HTTP_500/VERIFY_FAIL 等',

    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '结果说明,例如“DNS解析失败”“接口返回403”“verify接口业务校验失败”等',

    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP状态码。若请求未发出成功,可为空',

    `response_time_ms`             INT DEFAULT NULL COMMENT '本次测试总耗时,单位毫秒',


    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '请求流水号,用于串联应用日志',

    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号。若系统接入统一trace体系,可用于串联跨服务日志',

    `request_body`                 JSON DEFAULT NULL COMMENT '请求报文。注意不要塞入敏感明文',

    `response_body`                JSON DEFAULT NULL COMMENT '响应报文。建议保留必要字段即可,避免过大',

    `operator_id`                  BIGINT DEFAULT NULL COMMENT '操作人ID。若为系统自动探测可为空',

    `operator_name`                VARCHAR(100) DEFAULT NULL COMMENT '操作人姓名。若为系统自动探测可写 SYSTEM',

    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '操作来源IP',

    `remark`                       VARCHAR(500) DEFAULT NULL COMMENT '备注',

    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`) USING BTREE,

    KEY `idx_partner_id` (`partner_id`) USING BTREE,

    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,

    KEY `idx_connect_env` (`connect_env`) USING BTREE,

    KEY `idx_test_type` (`test_type`) USING BTREE,

    KEY `idx_connect_status` (`connect_status`) USING BTREE,

    KEY `idx_request_id` (`request_id`) USING BTREE,

    KEY `idx_trace_id` (`trace_id`) USING BTREE

) ENGINE=InnoDB

  DEFAULT CHARSET=utf8mb4

  COLLATE=utf8mb4_0900_ai_ci COMMENT='对方OA与verify接口连通性测试日志表';



-- =========================================================

-- SSO/JWT 换 token 主日志表

--

-- 这是新通信方式下最核心的一张日志表。

--

-- 记录一个完整链路:

-- 1)谁来申请

-- 2)提交了什么JWT关键信息

-- 3)基础校验是否通过

-- 4)nonce 是否命中重放

-- 5)verify接口是否调用成功、业务是否验证通过

-- 6)最终是否签发 access_token

--

-- 设计上把它当做“主流水表”

-- 而 verify 接口每次重试/调用明细,放到子表 bridge_sso_verify_log 里

-- =========================================================

DROP TABLE IF EXISTS `bridge_sso_exchange_log`;

CREATE TABLE `bridge_sso_exchange_log`

(

    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `request_id`                      VARCHAR(100) NOT NULL COMMENT '本次JWT换token请求流水号,建议全局唯一。用于串联应用日志、verify日志、token日志',

    `trace_id`                        VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号。若网关或链路系统已生成,可直接落库',


    `tenant_id`                       BIGINT DEFAULT NULL COMMENT '匹配到的我方企业唯一编码。若请求尚未成功映射到我方企业,可为空',

    `enterprise_code`                 VARCHAR(100) DEFAULT NULL COMMENT '请求中携带的企业统一社会信用代码,或根据partner配置映射到的信用代码',

    `partner_id`                      BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id。若还没匹配到企业,可为空',

    `partner_code`                    VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余,便于直接查看日志',

    `partner_name`                    VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余,便于直接查看日志',


    `exchange_direction`              VARCHAR(20) NOT NULL DEFAULT 'INBOUND' COMMENT '换token方向:INBOUND-对方拿JWT来换我方token;OUTBOUND-我方向对方提交JWT换对方token。当前场景通常是 INBOUND',

    `exchange_scene`                  VARCHAR(50) NOT NULL DEFAULT 'SSO_TOKEN_EXCHANGE' COMMENT '业务场景。当前固定可写 SSO_TOKEN_EXCHANGE,便于未来扩展',

    `exchange_env`                    VARCHAR(20) DEFAULT NULL COMMENT '执行环境:TEST/PRODUCTION',


    `source_ip`                       VARCHAR(50) DEFAULT NULL COMMENT '请求来源IP',

    `http_method`                     VARCHAR(20) DEFAULT NULL COMMENT '本次换token接口请求方式,通常为POST',

    `request_url`                     VARCHAR(1000) DEFAULT NULL COMMENT '本次请求命中的我方接口URL',

    `request_body`                    JSON DEFAULT NULL COMMENT '原始请求体。注意可存JWT脱敏值,不建议长期落完整超长敏感报文',


    `jwt_raw_preview`                 VARCHAR(500) DEFAULT NULL COMMENT '请求JWT脱敏预览值,例如前30位...后20位,便于人工排查',

    `jwt_hash`                        VARCHAR(255) DEFAULT NULL COMMENT '请求JWT摘要值。用于去重、追踪,不直接暴露原文',

    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '从JWT头部解析出的算法标识',

    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '从JWT claim中解析出的iss。若无则为空',

    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '从JWT claim中解析出的aud。若无则为空',

    `jwt_jti`                         VARCHAR(100) DEFAULT NULL COMMENT '从JWT claim中解析出的jti。若协议未要求可为空',

    `partner_tenant_id`               VARCHAR(100) DEFAULT NULL COMMENT '请求JWT里携带的发起方租户ID。这里保留字符串,兼容对方租户ID不一定是纯数字的情况',

    `request_enterprise_code`         VARCHAR(100) DEFAULT NULL COMMENT '请求JWT里携带的统一社会信用代码原值',

    `request_expire_time`             DATETIME DEFAULT NULL COMMENT '请求JWT里声明的过期时间。注意这是对方JWT本身的过期时间,不是我方access_token过期时间',

    `request_nonce`                   VARCHAR(200) DEFAULT NULL COMMENT '请求JWT里携带的nonce,用于防重放',


    `parse_status`                    TINYINT NOT NULL DEFAULT 0 COMMENT 'JWT解析结果:0-失败,1-成功',

    `parse_result_code`               VARCHAR(64) DEFAULT NULL COMMENT 'JWT解析结果码:SUCCESS/JWT_EMPTY/JWT_FORMAT_INVALID/JWT_DECODE_FAIL/JWT_HEADER_INVALID/JWT_CLAIM_INVALID 等',

    `parse_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT 'JWT解析结果说明',


    `claim_validate_status`           TINYINT NOT NULL DEFAULT 0 COMMENT 'claim基础校验结果:0-失败,1-成功',

    `claim_validate_code`             VARCHAR(64) DEFAULT NULL COMMENT 'claim校验结果码:SUCCESS/PARTNER_NOT_FOUND/ENTERPRISE_CODE_MISMATCH/EXPIRE_TIME_MISSING/JWT_EXPIRED/CLOCK_SKEW_INVALID/NONCE_MISSING/IP_DENIED/PARTNER_DISABLED/PARTNER_EXPIRED 等',

    `claim_validate_msg`              VARCHAR(1000) DEFAULT NULL COMMENT 'claim校验结果说明',

    `clock_skew_seconds`              INT DEFAULT NULL COMMENT '本次请求中,服务端计算出的时间偏差秒数。用于排查双方机器时间不一致问题',

    `nonce_check_status`              TINYINT NOT NULL DEFAULT 0 COMMENT 'nonce校验结果:0-未校验或失败,1-成功',

    `nonce_check_code`                VARCHAR(64) DEFAULT NULL COMMENT 'nonce校验结果码:SUCCESS/NONCE_MISSING/NONCE_REPLAY/NONCE_EXPIRED/NONCE_INVALID 等',

    `nonce_check_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT 'nonce校验结果说明',


    `verify_status`                   TINYINT NOT NULL DEFAULT 0 COMMENT '调用对方verify接口后的最终验证结果:0-失败,1-成功',

    `verify_result_code`              VARCHAR(64) DEFAULT NULL COMMENT 'verify最终结果码:SUCCESS/VERIFY_API_TIMEOUT/VERIFY_HTTP_FAIL/VERIFY_RESPONSE_INVALID/VERIFY_BUSINESS_REJECT 等',

    `verify_result_msg`               VARCHAR(1000) DEFAULT NULL COMMENT 'verify最终结果说明',

    `verify_attempt_count`            INT NOT NULL DEFAULT 0 COMMENT '本次换token流程中,verify接口共尝试调用了多少次。包括重试次数',

    `verify_success_time`             DATETIME DEFAULT NULL COMMENT 'verify最终成功时间。若未成功则为空',


    `token_issue_status`              TINYINT NOT NULL DEFAULT 0 COMMENT '我方access_token签发结果:0-未签发或失败,1-签发成功',

    `token_issue_code`                VARCHAR(64) DEFAULT NULL COMMENT '签发结果码:SUCCESS/VERIFY_NOT_PASS/TOKEN_GENERATE_FAIL/TOKEN_SAVE_FAIL/PARTNER_DISABLED 等',

    `token_issue_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT '签发结果说明',

    `issued_token_log_id`             BIGINT DEFAULT NULL COMMENT '若签发成功,对应 bridge_access_token_log.id,便于回查',

    `issued_access_token_preview`     VARCHAR(200) DEFAULT NULL COMMENT '签发成功后的token脱敏预览值,例如前20位...后10位,便于排查',

    `issued_expire_time`              DATETIME DEFAULT NULL COMMENT '本次签发的我方access_token过期时间',


    `final_status`                    VARCHAR(30) NOT NULL DEFAULT 'PROCESSING' COMMENT '整条换token链路最终状态:PROCESSING-处理中;SUCCESS-成功;FAILED-失败',

    `final_result_code`               VARCHAR(64) DEFAULT NULL COMMENT '整条链路最终结果码。通常可直接用来做统计报表',

    `final_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT '整条链路最终结果说明',

    `finished_time`                   DATETIME DEFAULT NULL COMMENT '整条链路完成时间。无论成功还是失败,只要流程结束就应写入',


    `remark`                          VARCHAR(500) DEFAULT NULL COMMENT '备注',

    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`) USING BTREE,

    UNIQUE KEY `uk_request_id` (`request_id`) USING BTREE,

    KEY `idx_trace_id` (`trace_id`) USING BTREE,

    KEY `idx_partner_id` (`partner_id`) USING BTREE,

    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,

    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,

    KEY `idx_request_nonce` (`request_nonce`) USING BTREE,

    KEY `idx_jwt_jti` (`jwt_jti`) USING BTREE,

    KEY `idx_verify_status` (`verify_status`) USING BTREE,

    KEY `idx_token_issue_status` (`token_issue_status`) USING BTREE,

    KEY `idx_final_status` (`final_status`) USING BTREE,

    KEY `idx_create_time` (`create_time`) USING BTREE

) ENGINE=InnoDB

  DEFAULT CHARSET=utf8mb4

  COLLATE=utf8mb4_0900_ai_ci COMMENT='SSO/JWT换token主日志表';



-- =========================================================

-- verify 接口调用明细日志表

--

-- 为什么单独拆出来:

-- 1)一次换token流程里,verify接口可能会重试多次

-- 2)主表 bridge_sso_exchange_log 只保留“最终结果”和“总尝试次数”

-- 3)本表保留每一次 verify 调用明细,便于排查:

--    - 第几次调用

--    - 调的是哪个URL

--    - 发了什么

--    - 返回了什么

--    - 是网络失败,还是业务拒绝

-- =========================================================

DROP TABLE IF EXISTS `bridge_sso_verify_log`;

CREATE TABLE `bridge_sso_verify_log`

(

    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `exchange_log_id`              BIGINT NOT NULL COMMENT '关联 bridge_sso_exchange_log.id',

    `request_id`                   VARCHAR(100) NOT NULL COMMENT '换token主请求流水号,冗余保存,便于不连表排查',

    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号',


    `tenant_id`                    BIGINT DEFAULT NULL COMMENT '企业唯一编码。若请求早期就失败且未映射成功,可为空',

    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码冗余',

    `partner_id`                   BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id',

    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',

    `partner_name`                 VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余',


    `verify_env`                   VARCHAR(20) DEFAULT NULL COMMENT '调用环境:TEST/PRODUCTION',

    `attempt_no`                   INT NOT NULL COMMENT '第几次调用,从1开始递增',

    `target_host`                  VARCHAR(500) DEFAULT NULL COMMENT '本次调用命中的host',

    `target_path`                  VARCHAR(500) DEFAULT NULL COMMENT '本次调用命中的verify路径',

    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次调用的完整URL',

    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,通常为POST',


    `request_jwt_preview`          VARCHAR(500) DEFAULT NULL COMMENT '本次提交给verify接口的JWT脱敏预览值',

    `request_nonce`                VARCHAR(200) DEFAULT NULL COMMENT '本次请求关联的nonce',

    `request_body`                 JSON DEFAULT NULL COMMENT '本次调用verify接口的请求报文',

    `response_body`                JSON DEFAULT NULL COMMENT '本次调用verify接口的响应报文',


    `call_status`                  TINYINT NOT NULL DEFAULT 0 COMMENT '本次调用是否成功拿到“可解析响应”:0-失败,1-成功',

    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '结果码:SUCCESS/TIMEOUT/CONNECT_FAIL/HTTP_403/HTTP_500/RESPONSE_INVALID/BUSINESS_REJECT 等',

    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '结果说明',

    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP状态码',

    `business_verify_status`       TINYINT DEFAULT NULL COMMENT '对方业务层验签结果:0-失败,1-成功。只有拿到业务响应时才有意义',

    `business_verify_code`         VARCHAR(64) DEFAULT NULL COMMENT '对方业务层返回的结果码,例如 SUCCESS/SIGN_INVALID/JWT_EXPIRED/NONCE_INVALID 等',

    `business_verify_msg`          VARCHAR(1000) DEFAULT NULL COMMENT '对方业务层返回的结果说明',

    `response_time_ms`             INT DEFAULT NULL COMMENT '本次verify调用耗时,单位毫秒',


    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',


    PRIMARY KEY (`id`) USING BTREE,

    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,

    KEY `idx_request_id` (`request_id`) USING BTREE,

    KEY `idx_partner_id` (`partner_id`) USING BTREE,

    KEY `idx_attempt_no` (`attempt_no`) USING BTREE,

    KEY `idx_call_status` (`call_status`) USING BTREE,

    KEY `idx_business_verify_status` (`business_verify_status`) USING BTREE,

    KEY `idx_create_time` (`create_time`) USING BTREE

) ENGINE=InnoDB

  DEFAULT CHARSET=utf8mb4

  COLLATE=utf8mb4_0900_ai_ci COMMENT='verify接口调用明细日志表';



-- =========================================================

-- access_token 签发日志表

--

-- 说明:

-- 1)新模式下,access_token 仍然是需要独立管理和审计的

-- 2)但它的来源不再是“app_key/app_secret login”

-- 3)而是“JWT + verify成功”之后的签发结果

--

-- 本表用于:

-- 1)记录签发了什么token

-- 2)何时签发、何时过期

-- 3)当前是否有效、是否吊销

-- 4)这个token来源于哪次 exchange 请求

--

-- 安全建议:

-- 1)建议长期只保留 token_hash + token_preview

-- 2)若当前阶段为了排障方便保留 token 明文,也建议后续收紧

-- =========================================================

DROP TABLE IF EXISTS `bridge_access_token_log`;

CREATE TABLE `bridge_access_token_log`

(

    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `exchange_log_id`              BIGINT DEFAULT NULL COMMENT '关联 bridge_sso_exchange_log.id。表示该token由哪次JWT换token流程签发出来',

    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '换token请求流水号冗余,便于不连表排查',

    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号',


    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',

    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码',

    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',

    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',

    `partner_name`                 VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余',


    `grant_type`                   VARCHAR(50) NOT NULL DEFAULT 'sso_jwt_exchange' COMMENT '授权来源类型。这里不再是传统 client_credentials,而是固定记为 sso_jwt_exchange,表示由SSO/JWT换token流程签发',

    `token_jti`                    VARCHAR(100) NOT NULL COMMENT '我方签发的access_token唯一编号。建议全局唯一,如 lower(replace(uuid(), ''-'', ''''))',

    `token`                        VARCHAR(2048) DEFAULT NULL COMMENT '签发的access_token明文。当前阶段如为排障方便可保留;后续建议关闭明文落库',

    `token_hash`                   VARCHAR(255) DEFAULT NULL COMMENT 'access_token摘要值。用于追踪、比对,不暴露明文',

    `token_preview`                VARCHAR(200) DEFAULT NULL COMMENT 'access_token脱敏预览值,例如前20位...后10位,便于人工排查',


    `issued_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '签发时间',

    `effective_time`               DATETIME DEFAULT NULL COMMENT '生效时间。通常等于签发时间;若存在延时生效策略可单独记录',

    `expire_time`                  DATETIME NOT NULL COMMENT '过期时间',

    `token_status`                 TINYINT NOT NULL DEFAULT 1 COMMENT 'token状态:0-失效,1-有效,2-已吊销',

    `revoke_time`                  DATETIME DEFAULT NULL COMMENT '吊销时间',

    `revoke_reason`                VARCHAR(500) DEFAULT NULL COMMENT '吊销原因,例如“企业停用”“安全事件”“人工禁用”',


    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '触发签发时的来源IP',

    `remark`                       VARCHAR(500) DEFAULT NULL COMMENT '备注',

    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    `update_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',


    PRIMARY KEY (`id`) USING BTREE,

    UNIQUE KEY `uk_token_jti` (`token_jti`) USING BTREE,

    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,

    KEY `idx_request_id` (`request_id`) USING BTREE,

    KEY `idx_partner_id` (`partner_id`) USING BTREE,

    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,

    KEY `idx_expire_time` (`expire_time`) USING BTREE,

    KEY `idx_token_status` (`token_status`) USING BTREE,

    KEY `idx_create_time` (`create_time`) USING BTREE

) ENGINE=InnoDB

  DEFAULT CHARSET=utf8mb4

  COLLATE=utf8mb4_0900_ai_ci COMMENT='access_token签发与状态日志表(来源于SSO/JWT换token)';



请把对应注释注释清楚,足够详细,需要沟通的日志也记录详细。不过原则是:最小最必要原则,不要过度冗余。

AI答:

下面我直接给你一版按你这次最终接口方案重新收敛后的 SQL。
这版重点做了几件事:

一、这次重构的核心取舍

1. 不再围绕 app_key / app_secret 设计

这次已经明确,核心认证链路变成:

发起方生成 encryption(本质上是 JWT)
→ 目标方收到后先做基础解析
→ 再拿这个 encryption 去请求对方 /api/oauth/verify
→ verify 通过后签发自己的 access_token

所以表结构不再把 app_key/app_secret 放在认证主模型里。

2. partner 主表只保留“必要配置”

只保留:
企业映射关系
环境地址
token/verify 路径
云模式/自建模式相关配置
连通性最新快照
必要安全参数

不把各种过程性字段堆进主表。

3. 日志分三层

第一层:bridge_sso_exchange_log
记录一次完整换 token 主流程

第二层:bridge_sso_verify_log
记录每次 verify 调用明细,便于排查重试、网络错误、业务拒绝

第三层:bridge_access_token_log
记录最终签发出来的 token 生命周期

4. 兼顾你说的“要存 encryption”

这里我做的是:
主日志表里保留:
encryption_preview 脱敏预览
encryption_hash 摘要
encryption_ciphertext 可选密文留档字段

这样满足你“要存下 encryption 便于追溯”的要求,同时又避免把原始值裸存成高风险明文。
如果你们当前阶段就是想直接存原值,也可以把 encryption_ciphertext 当“原样留存字段”先用,后续再切加密。

5. 自建模式补足 baseurl 解析能力

你这次特别强调了:

自建客户在换 token 前,需要先根据统一社会信用代码解析出 sso_baseurl

所以主表里我把:
测试、正式两个环境的 sso_baseurl
都保留下来,并明确说明:
自建模式优先用这个地址拼接 token/verify 接口。


下面是最终版 SQL。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- =========================================================
-- 对接企业主表
--
-- 设计目的:
-- 1)一个 partner 就是一家企业,但表名继续保留 partner,便于和领导、业务、接口文档沟通
-- 2)记录企业级对接主配置
-- 3)适配当前最终定下来的 SSO Token Exchange + 第三方 verify 校验方案
--
-- 当前认证模型:
-- 1)请求方调用 /api/oauth/getTokenBySso
-- 2)body 中仅传 encryption
-- 3)encryption 本质上是 JWT 字符串,内部至少包含:
--    - thirdparty
--    - module
--    - tenantId
--    - creditCode
--    - expireTime
--    - nonce
-- 4)目标系统收到后,先做基础校验
-- 5)再调用对方 /api/oauth/verify,确认该 encryption 是否确实由对方服务端签发
-- 6)验证通过后,再签发自己的 access_token
--
-- 本表只保留“配置”和“最新状态快照”
-- 过程日志、明细日志放到独立日志表,不把主表做成大杂烩
-- =========================================================
DROP TABLE IF EXISTS `bridge_partner`;
CREATE TABLE `bridge_partner`
(
    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `tenant_id`                       BIGINT NOT NULL COMMENT '我们系统中的企业唯一编码。你已明确:tenant_id 实际就是企业ID',
    `enterprise_code`                 VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码。双方租户映射、对接识别、日志关联的核心字段',
    `partner_code`                    VARCHAR(100) NOT NULL COMMENT '对接企业编码。虽然一个partner本质上就是一家企业,但仍保留 partner 叫法,例如 nuoming、zhipingyun',
    `partner_name`                    VARCHAR(255) NOT NULL COMMENT '对接企业名称',
    `enterprise_name`                 VARCHAR(255) DEFAULT NULL COMMENT '企业名称冗余字段,便于列表展示、日志排查、搜索过滤',

    `partner_effective_time`          DATETIME DEFAULT NULL COMMENT '企业对接生效时间。为空表示不限制起始时间',
    `partner_expire_time`             DATETIME DEFAULT NULL COMMENT '企业对接失效时间。超过该时间后,不允许再执行换token、verify、业务交互等',

    `deploy_mode`                     VARCHAR(20) NOT NULL DEFAULT 'CLOUD' COMMENT '默认部署模式:CLOUD-云模式;SELFBUILT-自建模式。用于该企业当前主流接入方式的默认值。单次请求里如果 encryption.module 有值,以请求值为准',
    `thirdparty_code`                 VARCHAR(100) NOT NULL COMMENT '对方系统在协议中的 thirdparty 标识。例如 zhipingyun、nuoming。调用 verify 时通常需要带上,用于让对方识别是哪个第三方系统',
    
    `api_host_test`                   VARCHAR(500) DEFAULT NULL COMMENT '对方测试环境基础地址。例如 https://test.xxx.com。适用于云模式或通用模式',
    `api_host_production`             VARCHAR(500) DEFAULT NULL COMMENT '对方正式环境基础地址。例如 https://api.xxx.com。适用于云模式或通用模式',

    `sso_baseurl_test`                VARCHAR(500) DEFAULT NULL COMMENT '对方测试环境 SSO 基础地址。自建模式下,通常需要先根据统一社会信用代码解析出该地址,再拼接 token / verify 接口',
    `sso_baseurl_production`          VARCHAR(500) DEFAULT NULL COMMENT '对方正式环境 SSO 基础地址。自建模式下优先使用该地址进行 /api/oauth/getTokenBySso 和 /api/oauth/verify 调用',

    `token_exchange_path`             VARCHAR(300) NOT NULL DEFAULT '/api/oauth/getTokenBySso' COMMENT '获取 token 的接口相对路径。按你当前最终方案固定为 /api/oauth/getTokenBySso,仍单独落库,便于以后小改而不改代码',
    `verify_path`                     VARCHAR(300) NOT NULL DEFAULT '/api/oauth/verify' COMMENT 'verify 接口相对路径。按你当前最终方案固定为 /api/oauth/verify',
    `token_exchange_http_method`      VARCHAR(20) NOT NULL DEFAULT 'POST' COMMENT '换 token 接口请求方式,当前固定为 POST',
    `verify_http_method`              VARCHAR(20) NOT NULL DEFAULT 'POST' COMMENT 'verify 接口请求方式,当前固定为 POST',

    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '协议约定的 JWT 算法标识,例如 HS256、RS256。这里主要用于协议记录与基础校验',
    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '协议约定的 JWT iss。若双方约定校验 iss,可在解析 encryption 时使用',
    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '协议约定的 JWT aud。若双方约定校验 aud,可在解析 encryption 时使用',
    `jwt_max_valid_seconds`           INT NOT NULL DEFAULT 300 COMMENT '允许对方 encryption 最大有效期秒数。即使对方写了很远的 expireTime,也不能超过该上限,防止签名长期有效',
    `allowed_clock_skew_seconds`      INT NOT NULL DEFAULT 300 COMMENT '双方服务器允许的时间偏差秒数。用于解决服务器时间略有不一致导致的误判',
    `nonce_expire_seconds`            INT NOT NULL DEFAULT 600 COMMENT 'nonce 防重放窗口,单位秒。超过该窗口的 nonce 即使 encryption 未完全过期,也可拒绝',
    `token_expire_seconds`            INT NOT NULL DEFAULT 7200 COMMENT '本系统在 verify 通过后签发给对方的 access_token 默认有效期,单位秒',

    `token_exchange_timeout_ms`       INT NOT NULL DEFAULT 5000 COMMENT '调用对方 getTokenBySso 接口的超时时间,单位毫秒。主要用于我方向对方换 token 的场景',
    `verify_timeout_ms`               INT NOT NULL DEFAULT 5000 COMMENT '调用对方 verify 接口的超时时间,单位毫秒',
    `verify_retry_count`              INT NOT NULL DEFAULT 0 COMMENT 'verify 接口失败后的最大重试次数。0 表示失败即结束,不重试',
    `verify_retry_interval_ms`        INT NOT NULL DEFAULT 0 COMMENT 'verify 重试间隔,单位毫秒。只有 verify_retry_count > 0 时才有意义',

    `ip_allow_list`                   VARCHAR(2000) DEFAULT NULL COMMENT '来源 IP 白名单,多个以英文逗号分隔。为空表示不限制。用于限制谁可以调用我方 getTokenBySso',
    `status`                          TINYINT NOT NULL DEFAULT 1 COMMENT '记录状态:0-停用,1-启用。停用后不允许换token、不允许业务交互',

    `oa_connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '最近一次连通性测试快照:0-未测试,1-成功,2-失败',
    `oa_connect_env`                  VARCHAR(20) DEFAULT NULL COMMENT '最近一次测试环境:TEST/PRODUCTION',
    `oa_connect_test_type`            VARCHAR(30) DEFAULT NULL COMMENT '最近一次测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token链路测试',
    `oa_connect_time`                 DATETIME DEFAULT NULL COMMENT '最近一次点击“连通对方OA”或系统自动连通性检测的时间',
    `oa_connect_result_code`          VARCHAR(64) DEFAULT NULL COMMENT '最近一次连通性测试结果码,例如 SUCCESS、TIMEOUT、HTTP_403、VERIFY_FAIL、DNS_ERROR',
    `oa_connect_result_msg`           VARCHAR(1000) DEFAULT NULL COMMENT '最近一次连通性测试结果说明',
    `oa_connect_response_time_ms`     INT DEFAULT NULL COMMENT '最近一次连通性测试总耗时,单位毫秒',
    `oa_connect_by`                   BIGINT DEFAULT NULL COMMENT '最近一次执行连通性测试的操作人ID。系统自动探测可为空',
    `oa_connect_by_name`              VARCHAR(100) DEFAULT NULL COMMENT '最近一次执行连通性测试的操作人名称。系统自动探测可写 SYSTEM',

    `remark`                          VARCHAR(1000) DEFAULT NULL COMMENT '备注。可记录该企业的特殊对接约定、异常说明、上线注意事项',
    `created_by`                      BIGINT DEFAULT NULL COMMENT '创建人',
    `updated_by`                      BIGINT DEFAULT NULL COMMENT '更新人',
    `is_deleted`                      TINYINT NOT NULL DEFAULT 0 COMMENT '是否逻辑删除:0-否,1-是',
    `deleted_time`                    DATETIME DEFAULT NULL COMMENT '逻辑删除时间',
    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_tenant_id` (`tenant_id`) USING BTREE,
    UNIQUE KEY `uk_partner_code` (`partner_code`) USING BTREE,
    UNIQUE KEY `uk_enterprise_code` (`enterprise_code`) USING BTREE,

    KEY `idx_partner_name` (`partner_name`) USING BTREE,
    KEY `idx_status` (`status`) USING BTREE,
    KEY `idx_deploy_mode` (`deploy_mode`) USING BTREE,
    KEY `idx_partner_expire_time` (`partner_expire_time`) USING BTREE,
    KEY `idx_oa_connect_status` (`oa_connect_status`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='对接企业主表(新 SSO/JWT 模式主配置表,一个 partner 即一家企业)';


-- =========================================================
-- 对方 OA / SSO 接口连通性测试日志表
--
-- 用途:
-- 1)记录每次点击“连通对方OA”的历史
-- 2)记录测试的是基础地址、verify 接口,还是完整 getTokenBySso 链路
-- 3)bridge_partner 只留最新快照,本表保留全量历史
--
-- 最小必要原则:
-- 1)保留关键请求目标、耗时、结果码、结果说明
-- 2)请求报文 / 响应报文只建议留必要字段,避免过大
-- =========================================================
DROP TABLE IF EXISTS `bridge_partner_connectivity_log`;
CREATE TABLE `bridge_partner_connectivity_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',
    `enterprise_code`              VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码,冗余保存,便于按信用代码直接检索',
    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',

    `connect_env`                  VARCHAR(20) NOT NULL COMMENT '测试环境:TEST/PRODUCTION',
    `deploy_mode`                  VARCHAR(20) DEFAULT NULL COMMENT '本次测试使用的部署模式:CLOUD/SELFBUILT',
    `test_type`                    VARCHAR(30) NOT NULL COMMENT '测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token测试',
    `target_host`                  VARCHAR(500) DEFAULT NULL COMMENT '本次测试命中的 host 或 baseurl',
    `target_path`                  VARCHAR(300) DEFAULT NULL COMMENT '本次测试命中的接口路径。例如 /api/oauth/verify 或 /api/oauth/getTokenBySso',
    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次实际请求的完整 URL',
    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,例如 GET/POST',

    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '本次测试请求流水号。用于串联应用日志',
    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号。若接入统一 trace 体系,可用于跨服务排查',
    `request_body`                 JSON DEFAULT NULL COMMENT '请求报文。建议只保留必要字段,避免敏感信息直接明文落库',
    `response_body`                JSON DEFAULT NULL COMMENT '响应报文。建议只保留关键字段,例如 code、msg、success',

    `connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '测试结果:0-失败,1-成功',
    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '结果码:SUCCESS、TIMEOUT、DNS_ERROR、SSL_ERROR、HTTP_403、HTTP_500、VERIFY_FAIL 等',
    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '结果说明,例如“DNS解析失败”“verify接口返回业务失败”',
    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP 状态码。若请求未成功发出,可为空',
    `response_time_ms`             INT DEFAULT NULL COMMENT '本次测试总耗时,单位毫秒',

    `operator_id`                  BIGINT DEFAULT NULL COMMENT '操作人ID。若为系统自动探测可为空',
    `operator_name`                VARCHAR(100) DEFAULT NULL COMMENT '操作人姓名。若为系统自动探测可写 SYSTEM',
    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '操作来源IP',
    `remark`                       VARCHAR(500) DEFAULT NULL COMMENT '备注',
    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_connect_env` (`connect_env`) USING BTREE,
    KEY `idx_test_type` (`test_type`) USING BTREE,
    KEY `idx_connect_status` (`connect_status`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_trace_id` (`trace_id`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='对方OA与SSO接口连通性测试日志表';


-- =========================================================
-- SSO/JWT 换 token 主日志表
--
-- 这是当前通信方式下最核心的一张主流水日志表
--
-- 记录内容包括:
-- 1)是谁来申请 token
-- 2)带来的 encryption 是什么特征值
-- 3)基础解析是否通过
-- 4)claim 校验是否通过
-- 5)nonce 是否命中重放
-- 6)verify 是否通过
-- 7)最终是否签发 access_token
--
-- 说明:
-- 1)这里的 encryption 指接口 body 中传入的那个字段
-- 2)它本质上通常是 JWT 字符串
-- 3)为了满足你“要存下 encryption”的要求,本表提供:
--    - encryption_preview:脱敏预览
--    - encryption_hash:摘要
--    - encryption_ciphertext:可选留存值
-- 4)不建议长期直接裸存完整明文;若现阶段为了排障需要,也建议后续再收紧
-- =========================================================
DROP TABLE IF EXISTS `bridge_sso_exchange_log`;
CREATE TABLE `bridge_sso_exchange_log`
(
    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `request_id`                      VARCHAR(100) NOT NULL COMMENT '本次换token请求流水号,建议全局唯一。用于串联应用日志、verify日志、token日志',
    `trace_id`                        VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号。若网关或链路系统已生成,可直接落库',

    `tenant_id`                       BIGINT DEFAULT NULL COMMENT '匹配到的我方企业唯一编码。若在早期校验阶段失败,尚未匹配成功,则可为空',
    `enterprise_code`                 VARCHAR(100) DEFAULT NULL COMMENT '最终识别到的企业统一社会信用代码。通常来自 encryption.creditCode 或 partner 映射结果',
    `partner_id`                      BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id。若尚未匹配成功,可为空',
    `partner_code`                    VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余,便于不连表排查',
    `partner_name`                    VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余,便于日志直接查看',

    `exchange_direction`              VARCHAR(20) NOT NULL DEFAULT 'INBOUND' COMMENT '换token方向:INBOUND-对方拿 encryption 来换我方 token;OUTBOUND-我方向对方提交 encryption 换对方 token',
    `exchange_scene`                  VARCHAR(50) NOT NULL DEFAULT 'SSO_TOKEN_EXCHANGE' COMMENT '业务场景。当前固定写 SSO_TOKEN_EXCHANGE,便于未来扩展',
    `exchange_env`                    VARCHAR(20) DEFAULT NULL COMMENT '执行环境:TEST/PRODUCTION',
    `deploy_mode`                     VARCHAR(20) DEFAULT NULL COMMENT '本次请求中的模式:CLOUD/SELFBUILT。优先取 encryption.module;若没有再回落 partner 默认配置',

    `source_ip`                       VARCHAR(50) DEFAULT NULL COMMENT '请求来源IP',
    `http_method`                     VARCHAR(20) DEFAULT NULL COMMENT '本次换token接口请求方式,通常为 POST',
    `request_url`                     VARCHAR(1000) DEFAULT NULL COMMENT '本次请求命中的我方接口 URL',
    `request_body`                    JSON DEFAULT NULL COMMENT '原始请求体。建议仅保留必要字段,例如 encryption 脱敏值,不建议长期存完整敏感明文',

    `encryption_preview`              VARCHAR(500) DEFAULT NULL COMMENT '请求中 encryption 的脱敏预览值,例如前30位...后20位,便于人工排查',
    `encryption_hash`                 VARCHAR(255) DEFAULT NULL COMMENT 'encryption 摘要值。用于去重、追踪、防重复排查,不直接暴露原文',
    `encryption_ciphertext`           TEXT DEFAULT NULL COMMENT 'encryption 留存值。建议存加密后的密文,而不是直接裸存原文。用于满足审计、追溯、问题复盘场景',
    
    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '从 encryption 的 JWT 头部解析出的算法标识',
    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 iss。若无则为空',
    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 aud。若无则为空',
    `jwt_jti`                         VARCHAR(100) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 jti。若协议未使用可为空',

    `request_thirdparty`              VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 thirdparty,例如 zhipingyun。verify 时通常会带这个值,表示由哪个第三方系统发起',
    `request_module`                  VARCHAR(20) DEFAULT NULL COMMENT '从 encryption 中解析出的 module,通常为 CLOUD/SELFBUILT',
    `partner_tenant_id`               VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 tenantId。保留字符串类型,兼容对方租户ID不一定是纯数字',
    `request_enterprise_code`         VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 creditCode 原值',
    `request_expire_time`             DATETIME DEFAULT NULL COMMENT '从 encryption 中解析出的 expireTime,对应请求签名自身的过期时间',
    `request_nonce`                   VARCHAR(200) DEFAULT NULL COMMENT '从 encryption 中解析出的 nonce,用于防重放',

    `parse_status`                    TINYINT NOT NULL DEFAULT 0 COMMENT 'encryption 解析结果:0-失败,1-成功',
    `parse_result_code`               VARCHAR(64) DEFAULT NULL COMMENT '解析结果码:SUCCESS、ENCRYPTION_EMPTY、JWT_FORMAT_INVALID、JWT_DECODE_FAIL、JWT_HEADER_INVALID、JWT_CLAIM_INVALID 等',
    `parse_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT '解析结果说明',

    `claim_validate_status`           TINYINT NOT NULL DEFAULT 0 COMMENT 'claim 基础校验结果:0-失败,1-成功',
    `claim_validate_code`             VARCHAR(64) DEFAULT NULL COMMENT 'claim 校验结果码:SUCCESS、PARTNER_NOT_FOUND、ENTERPRISE_CODE_MISMATCH、THIRDPARTY_MISMATCH、MODULE_INVALID、JWT_EXPIRED、CLOCK_SKEW_INVALID、IP_DENIED、PARTNER_DISABLED、PARTNER_EXPIRED 等',
    `claim_validate_msg`              VARCHAR(1000) DEFAULT NULL COMMENT 'claim 基础校验结果说明',
    `clock_skew_seconds`              INT DEFAULT NULL COMMENT '服务端计算出的时间偏差秒数。用于排查双方服务器时间不一致问题',

    `nonce_check_status`              TINYINT NOT NULL DEFAULT 0 COMMENT 'nonce 校验结果:0-未校验或失败,1-成功',
    `nonce_check_code`                VARCHAR(64) DEFAULT NULL COMMENT 'nonce 校验结果码:SUCCESS、NONCE_MISSING、NONCE_REPLAY、NONCE_EXPIRED、NONCE_INVALID 等',
    `nonce_check_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT 'nonce 校验结果说明',

    `verify_status`                   TINYINT NOT NULL DEFAULT 0 COMMENT '调用对方 verify 接口后的最终验证结果:0-失败,1-成功',
    `verify_result_code`              VARCHAR(64) DEFAULT NULL COMMENT 'verify 最终结果码:SUCCESS、VERIFY_API_TIMEOUT、VERIFY_HTTP_FAIL、VERIFY_RESPONSE_INVALID、VERIFY_BUSINESS_REJECT 等',
    `verify_result_msg`               VARCHAR(1000) DEFAULT NULL COMMENT 'verify 最终结果说明',
    `verify_attempt_count`            INT NOT NULL DEFAULT 0 COMMENT '本次换token流程中,verify 接口共尝试调用了多少次,包括重试次数',
    `verify_success_time`             DATETIME DEFAULT NULL COMMENT 'verify 最终成功时间。未成功则为空',

    `token_issue_status`              TINYINT NOT NULL DEFAULT 0 COMMENT '我方 access_token 签发结果:0-未签发或失败,1-签发成功',
    `token_issue_code`                VARCHAR(64) DEFAULT NULL COMMENT '签发结果码:SUCCESS、VERIFY_NOT_PASS、TOKEN_GENERATE_FAIL、TOKEN_SAVE_FAIL、PARTNER_DISABLED 等',
    `token_issue_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT '签发结果说明',
    `issued_token_log_id`             BIGINT DEFAULT NULL COMMENT '若签发成功,对应 bridge_access_token_log.id,便于回查',
    `issued_access_token_preview`     VARCHAR(200) DEFAULT NULL COMMENT '签发成功后的 token 脱敏预览值,例如前20位...后10位',
    `issued_expire_time`              DATETIME DEFAULT NULL COMMENT '本次签发的我方 access_token 过期时间',

    `final_status`                    VARCHAR(30) NOT NULL DEFAULT 'PROCESSING' COMMENT '整条换token链路最终状态:PROCESSING-处理中;SUCCESS-成功;FAILED-失败',
    `final_result_code`               VARCHAR(64) DEFAULT NULL COMMENT '整条链路最终结果码。通常可直接作为统计报表口径',
    `final_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT '整条链路最终结果说明',
    `finished_time`                   DATETIME DEFAULT NULL COMMENT '整条链路完成时间。无论成功还是失败,只要流程结束就应写入',

    `remark`                          VARCHAR(500) DEFAULT NULL COMMENT '备注',
    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_request_id` (`request_id`) USING BTREE,
    KEY `idx_trace_id` (`trace_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,
    KEY `idx_request_nonce` (`request_nonce`) USING BTREE,
    KEY `idx_jwt_jti` (`jwt_jti`) USING BTREE,
    KEY `idx_encryption_hash` (`encryption_hash`) USING BTREE,
    KEY `idx_verify_status` (`verify_status`) USING BTREE,
    KEY `idx_token_issue_status` (`token_issue_status`) USING BTREE,
    KEY `idx_final_status` (`final_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='SSO/JWT 换 token 主日志表';


-- =========================================================
-- verify 接口调用明细日志表
--
-- 设计原因:
-- 1)一次换token流程里,verify 可能会调用多次
-- 2)主表只保留 verify 最终结果和总尝试次数
-- 3)本表记录每一次 verify 调用的明细
--
-- 按你当前协议:
-- verify 接口 body 至少会带:
-- 1)thirdparty
-- 2)encryption
--
-- 本表里同时记录:
-- 1)请求给谁
-- 2)发了什么关键字段
-- 3)返回了什么
-- 4)是网络失败,还是业务校验失败
-- =========================================================
DROP TABLE IF EXISTS `bridge_sso_verify_log`;
CREATE TABLE `bridge_sso_verify_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `exchange_log_id`              BIGINT NOT NULL COMMENT '关联 bridge_sso_exchange_log.id',
    `request_id`                   VARCHAR(100) NOT NULL COMMENT '换token主请求流水号冗余,便于不连表排查',
    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号',

    `tenant_id`                    BIGINT DEFAULT NULL COMMENT '企业唯一编码。若请求在早期失败,尚未匹配成功,可为空',
    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码冗余',
    `partner_id`                   BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id',
    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',
    `partner_name`                 VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余',

    `verify_env`                   VARCHAR(20) DEFAULT NULL COMMENT '调用环境:TEST/PRODUCTION',
    `deploy_mode`                  VARCHAR(20) DEFAULT NULL COMMENT '本次 verify 使用的部署模式:CLOUD/SELFBUILT',
    `attempt_no`                   INT NOT NULL COMMENT '第几次调用,从1开始递增',
    `target_host`                  VARCHAR(500) DEFAULT NULL COMMENT '本次调用命中的 host 或 baseurl',
    `target_path`                  VARCHAR(300) DEFAULT NULL COMMENT '本次调用命中的 verify 路径,通常为 /api/oauth/verify',
    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次调用的完整 URL',
    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,通常为 POST',

    `request_thirdparty`           VARCHAR(100) DEFAULT NULL COMMENT '本次请求 verify 时提交的 thirdparty 值',
    `request_encryption_preview`   VARCHAR(500) DEFAULT NULL COMMENT '本次提交给 verify 接口的 encryption 脱敏预览值',
    `request_encryption_hash`      VARCHAR(255) DEFAULT NULL COMMENT '本次提交给 verify 接口的 encryption 摘要值',
    `request_nonce`                VARCHAR(200) DEFAULT NULL COMMENT '本次请求关联的 nonce',
    `request_body`                 JSON DEFAULT NULL COMMENT '本次调用 verify 接口的请求报文。建议只保留必要字段',
    `response_body`                JSON DEFAULT NULL COMMENT '本次调用 verify 接口的响应报文。建议只保留 success、error 等关键字段',

    `call_status`                  TINYINT NOT NULL DEFAULT 0 COMMENT '本次调用是否成功拿到“可解析响应”:0-失败,1-成功',
    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '调用层结果码:SUCCESS、TIMEOUT、CONNECT_FAIL、HTTP_403、HTTP_500、RESPONSE_INVALID、BUSINESS_REJECT 等',
    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '调用层结果说明',
    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP 状态码。若请求未发出成功,可为空',

    `business_verify_status`       TINYINT DEFAULT NULL COMMENT '对方业务层验签结果:0-失败,1-成功。只有拿到业务响应时才有意义',
    `business_verify_code`         VARCHAR(64) DEFAULT NULL COMMENT '对方业务层结果码,例如 SUCCESS、SIGN_INVALID、JWT_EXPIRED、NONCE_INVALID 等',
    `business_verify_msg`          VARCHAR(1000) DEFAULT NULL COMMENT '对方业务层结果说明',
    `response_time_ms`             INT DEFAULT NULL COMMENT '本次 verify 调用耗时,单位毫秒',

    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`) USING BTREE,
    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_attempt_no` (`attempt_no`) USING BTREE,
    KEY `idx_call_status` (`call_status`) USING BTREE,
    KEY `idx_business_verify_status` (`business_verify_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='verify 接口调用明细日志表';


-- =========================================================
-- access_token 签发与状态日志表
--
-- 说明:
-- 1)当前 access_token 的来源不再是 app_key/app_secret
-- 2)而是 encryption + verify 成功之后的签发结果
-- 3)本表用于记录 token 的签发、有效、过期、吊销状态
--
-- 安全建议:
-- 1)优先保留 token_hash + token_preview
-- 2)token 明文仅在当前排障阶段短期保留,后续建议收紧
-- =========================================================
DROP TABLE IF EXISTS `bridge_access_token_log`;
CREATE TABLE `bridge_access_token_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `exchange_log_id`              BIGINT DEFAULT NULL COMMENT '关联 bridge_sso_exchange_log.id。表示该 token 来源于哪次换 token 流程',
    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '换token请求流水号冗余,便于不连表排查',
    `trace_id`                     VARCHAR(100) DEFAULT NULL COMMENT '链路追踪号',

    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',
    `enterprise_code`              VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码',
    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',
    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',
    `partner_name`                 VARCHAR(255) DEFAULT NULL COMMENT '对接企业名称冗余',

    `grant_type`                   VARCHAR(50) NOT NULL DEFAULT 'sso_jwt_exchange' COMMENT '授权来源类型。当前固定为 sso_jwt_exchange,表示由 SSO/JWT 换 token 流程签发',
    `token_jti`                    VARCHAR(100) NOT NULL COMMENT '我方签发的 access_token 唯一编号。建议全局唯一,例如 lower(replace(uuid(), ''-'', ''''))',
    `token`                        VARCHAR(2048) DEFAULT NULL COMMENT '签发的 access_token 明文。当前如为排障方便可保留;后续建议关闭明文落库',
    `token_hash`                   VARCHAR(255) DEFAULT NULL COMMENT 'access_token 摘要值。用于追踪、校验,不暴露明文',
    `token_preview`                VARCHAR(200) DEFAULT NULL COMMENT 'access_token 脱敏预览值,例如前20位...后10位',

    `issued_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '签发时间',
    `effective_time`               DATETIME DEFAULT NULL COMMENT '生效时间。通常等于签发时间;若将来有延迟生效需求,可单独记录',
    `expire_time`                  DATETIME NOT NULL COMMENT '过期时间',
    `token_status`                 TINYINT NOT NULL DEFAULT 1 COMMENT 'token 状态:0-失效,1-有效,2-已吊销',
    `revoke_time`                  DATETIME DEFAULT NULL COMMENT '吊销时间',
    `revoke_reason`                VARCHAR(500) DEFAULT NULL COMMENT '吊销原因,例如企业停用、安全事件、人工禁用',

    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '触发签发时的来源IP',
    `remark`                       VARCHAR(500) DEFAULT NULL COMMENT '备注',
    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_token_jti` (`token_jti`) USING BTREE,
    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,
    KEY `idx_expire_time` (`expire_time`) USING BTREE,
    KEY `idx_token_status` (`token_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='access_token 签发与状态日志表(来源于 SSO/JWT 换 token)';

SET FOREIGN_KEY_CHECKS = 1;

二、这版相比你原稿,我做了哪些关键修正

1. 把接口语义彻底统一成 encryption

你最终接口文档里,参数名已经明确不是 signature,而是 encryption
所以我在日志表里不再混用 signature/jwt 作为主命名,而是统一以 encryption 为核心字段名。

当然注释里我已经写清楚:
encryption 本质上通常就是 JWT 字符串。

这样有两个好处:

第一,和接口文档完全一致

前端、后端、接口文档、日志表,命名统一,不会沟通错位。

第二,兼容未来

以后即便你们把 JWT 套一层别的封装,字段名还是 encryption,表结构也不用改。

2. 增加了 deploy_mode + sso_baseurl

这是你这次补充里最关键但你原表还不够落地的点。

你明确说了:

自建客户的获取 token 和 verify 地址,不一定跟云模式一样,
需要先根据统一社会信用代码解析出 sso_baseurl

所以我在 bridge_partner 中明确加了:

sso_baseurl_test
sso_baseurl_production

并且保留了:

api_host_test
api_host_production

这样以后实际拼接地址时,逻辑可以非常清晰:

云模式

优先走 api_host_xxx + path

自建模式

优先走 sso_baseurl_xxx + path

这样不会把“普通业务 host”和“SSO host”混为一谈。

3. 主日志里补了 encryption 的三种留存方式

你提了一个很明确的要求:

“我们接着解密并存下这个 encryption,执行日志记录啊,跟这个 encryption 里的信用代码关联”

这件事如果简单粗暴做,很多人会直接存明文。
但那样风险太高。

所以我做成三层:

encryption_preview

给人看,排查方便

encryption_hash

给程序查重、检索、比对

encryption_ciphertext

满足你“要留存”的要求

这就兼顾了:

审计
排障
安全

而不是为了“能查问题”把敏感值直接全量裸存。

4. verify 日志单独记录 thirdparty

你这次 verify 接口中,已经非常明确:

body 里至少会带
thirdparty
encryption

所以我在 bridge_sso_verify_log 里加了:

request_thirdparty

这样以后排查时可以直接回答这些问题:

这次 verify 是以哪个第三方身份去验的
是不是 thirdparty 传错了
同一个 encryption 是否被错误地拿去给另一个 thirdparty 验了

这在联调时非常有用。

5. 减少过度冗余

你强调“最小最必要原则,不要过度冗余”。

所以我刻意没有再加下面这些容易越堆越乱的字段:

超多重复的 host/path 快照
大量无必要的 operator 冗余
过细碎的状态位拆分
不必要的 JSON 原样全量落库

我保留的是“真排障时能用上”的字段,而不是“看起来很全但实际上没人查”的字段。

三、这套表的实际职责边界

1. bridge_partner

只负责“企业主配置 + 最新连通性快照”

不要把过程性明细写回这里
否则主表很快会被污染

2. bridge_partner_connectivity_log

只负责“点一下连通对方OA”这类测试行为

包括:
基础 host 探测
verify 接口探测
完整 token 交换探测

它不是正式业务流水表

3. bridge_sso_exchange_log

正式换 token 主流水表

只要有人真实调用了 /api/oauth/getTokenBySso
或者我方向别人真实发起换 token
就应该有一条主记录

4. bridge_sso_verify_log

正式 verify 明细表

一次 exchange 可以对应多条 verify 记录
尤其是超时重试场景

5. bridge_access_token_log

正式 token 生命周期表

它是“结果表”,不是“过程表”

四、你落地时要特别注意的几个实现点

1. nonce 防重放不要只靠日志表查

日志表是审计用的,不适合当高并发实时判重主结构。
真正在线判重,建议你还是:

Redis
或独立 nonce 缓存键

日志表只保留审计结果:
成功
重复
过期

2. encryption_hash 建议统一算法

建议统一用固定摘要算法,例如:

SHA-256

这样以后查询和比对标准一致。

3. request_expire_time 建议统一转成 DATETIME 落库

你协议里给的是时间戳。
数据库里落成 DATETIME 更利于排查。

4. encryption_ciphertext 真要存,建议应用层加密后再存

不要直接“数据库文本字段 = 原始 encryption 明文”。

更稳妥的是:
应用层 AES 加密
数据库只存密文

5. verify 返回结构最好做统一归一化

你现在给的 verify 返回格式是:

成功:
success: true

失败:
success: false
error: [...]

建议你在程序里统一解析成:

业务是否成功
业务码
业务消息

然后分别落:
business_verify_status
business_verify_code
business_verify_msg

这样统计时最方便。

五、我对你这版方案的总体判断

这版方案已经比“app_key/app_secret 直登”合理很多,核心优势就在于:

1. 不需要双方长期持有对方 secret

这点非常关键。
尤其一体化集成场景,客户侧配置越少越好。

2. encryption 只是短期票据

即使泄漏,也有:
过期时间
nonce
服务端 verify 二次确认

风险比长期静态秘钥小得多。

3. verify 机制补上了“防伪造”这一刀

这一点才是这套设计真正成立的关键。
否则只靠“统一社会信用代码 + 可公开字段 + 约定加密方式”,是扛不住伪造的。

4. 云模式 / 自建模式都能兼容

只要 baseurl 解析逻辑做好,就能覆盖。

我问:

`partner_effective_time`          DATETIME DEFAULT NULL COMMENT '企业对接生效时间。为空表示不限制起始时间',

`partner_expire_time`             DATETIME DEFAULT NULL COMMENT '企业对接失效时间。超过该时间后,不允许再执行换token、verify、业务交互等',

这俩跟系统的企业生效失效时间默认一致。

服务端计算出的时间偏差秒数这个我拿什么计算,请详细注释。

bridge_sso_exchange_log这张表每个字段是我方调,还是对方调,请明确详细注释。

他调用我的verify记录在哪里?请你也明确注释。

请问你以上这几张表是真的最小必要表吗?如果是就保持不变,不是的话,请优化下。另外冗余字段感觉设计有点过度,请你适当考虑,如果确有必要就保留。只输出sql,注释写在sql注释或者sql语句注释里。

AI答:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- =========================================================
-- 对接企业主表
--
-- 设计定位:
-- 1)一个 partner 就是一家企业,但仍保留 partner 命名,便于与领导、业务、接口文档沟通
-- 2)记录企业级对接主配置
-- 3)适配当前最终确定的 SSO Token Exchange + verify 二次校验方案
--
-- 最小必要原则说明:
-- 1)本表只放“静态配置 + 最新连通性快照”
-- 2)不把换 token 过程日志、verify 调用明细、token 生命周期塞进主表
-- 3)企业名称等只保留最必要冗余,避免后续日志排查完全依赖连表
--
-- 关于 partner_effective_time / partner_expire_time:
-- 1)这两个字段默认应与系统企业主数据中的生效/失效时间保持一致
-- 2)建议在创建 partner 配置时,从企业主表同步写入
-- 3)若后续企业主数据时间发生变更,建议业务侧同步更新此表
-- 4)本表仍保留独立字段,而不直接省掉,是因为对接链路校验常常需要“就地取值”
--    若完全依赖外部企业表,排查和历史审计会变复杂
-- =========================================================
DROP TABLE IF EXISTS `bridge_partner`;
CREATE TABLE `bridge_partner`
(
    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',

    `tenant_id`                       BIGINT NOT NULL COMMENT '我方系统中的企业唯一编码。你已明确:tenant_id 实际就是企业ID',
    `enterprise_code`                 VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码。双方租户映射、请求识别、日志关联的核心字段',
    `partner_code`                    VARCHAR(100) NOT NULL COMMENT '对接企业编码。虽然一个partner本质就是一家企业,但仍保留 partner 叫法,例如 nuoming、zhipingyun',
    `partner_name`                    VARCHAR(255) NOT NULL COMMENT '对接企业名称',

    `partner_effective_time`          DATETIME DEFAULT NULL COMMENT '企业对接生效时间。默认应与系统企业主数据中的生效时间一致;为空表示不限制起始时间',
    `partner_expire_time`             DATETIME DEFAULT NULL COMMENT '企业对接失效时间。默认应与系统企业主数据中的失效时间一致;超过该时间后,不允许再执行换token、verify、业务交互等',

    `deploy_mode`                     VARCHAR(20) NOT NULL DEFAULT 'CLOUD' COMMENT '默认部署模式:CLOUD-云模式;SELFBUILT-自建模式。单次请求若 encryption.module 有值,则运行时以请求值为准',
    `thirdparty_code`                 VARCHAR(100) NOT NULL COMMENT '对方系统在协议中的 thirdparty 标识。例如 zhipingyun、nuoming。调用对方 verify 时通常需要带上,用于让对方识别请求来源',

    `api_host_test`                   VARCHAR(500) DEFAULT NULL COMMENT '对方测试环境基础地址。例如 https://test.xxx.com。适用于云模式或通用模式',
    `api_host_production`             VARCHAR(500) DEFAULT NULL COMMENT '对方正式环境基础地址。例如 https://api.xxx.com。适用于云模式或通用模式',
    `sso_baseurl_test`                VARCHAR(500) DEFAULT NULL COMMENT '对方测试环境 SSO 基础地址。自建模式下,通常需要先根据统一社会信用代码解析出该地址,再拼接 token/verify 路径',
    `sso_baseurl_production`          VARCHAR(500) DEFAULT NULL COMMENT '对方正式环境 SSO 基础地址。自建模式下优先使用该地址进行 /api/oauth/getTokenBySso 和 /api/oauth/verify 调用',

    `token_exchange_path`             VARCHAR(300) NOT NULL DEFAULT '/api/oauth/getTokenBySso' COMMENT '获取 token 的接口相对路径。按当前最终方案固定为 /api/oauth/getTokenBySso,独立落库便于未来调整',
    `verify_path`                     VARCHAR(300) NOT NULL DEFAULT '/api/oauth/verify' COMMENT 'verify 接口相对路径。按当前最终方案固定为 /api/oauth/verify',
    `token_exchange_http_method`      VARCHAR(20) NOT NULL DEFAULT 'POST' COMMENT '换 token 接口请求方式,当前固定为 POST',
    `verify_http_method`              VARCHAR(20) NOT NULL DEFAULT 'POST' COMMENT 'verify 接口请求方式,当前固定为 POST',

    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '协议约定的 JWT 算法标识,例如 HS256、RS256。主要用于协议记录与基础校验',
    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '协议约定的 JWT iss。若双方约定校验 iss,可在解析 encryption 时使用',
    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '协议约定的 JWT aud。若双方约定校验 aud,可在解析 encryption 时使用',
    `jwt_max_valid_seconds`           INT NOT NULL DEFAULT 300 COMMENT '允许对方 encryption 的最大有效期秒数。即使对方写了更远的 expireTime,也不能超过该上限,防止短期票据被做成长期票据',
    `allowed_clock_skew_seconds`      INT NOT NULL DEFAULT 300 COMMENT '双方服务器允许的时钟偏差秒数。用于解决服务器时间略有不一致导致的误判。例如对方 expireTime=12:00:00,我方当前时间=12:00:20,若允许偏差300秒,则仍可视为未超限',
    `nonce_expire_seconds`            INT NOT NULL DEFAULT 600 COMMENT 'nonce 防重放窗口,单位秒。超过该窗口的 nonce 即使 encryption 尚未完全过期,也可按业务拒绝',
    `token_expire_seconds`            INT NOT NULL DEFAULT 7200 COMMENT '我方在 verify 通过后签发给对方的 access_token 默认有效期,单位秒',

    `token_exchange_timeout_ms`       INT NOT NULL DEFAULT 5000 COMMENT '我方向对方调用 getTokenBySso 时的超时时间,单位毫秒',
    `verify_timeout_ms`               INT NOT NULL DEFAULT 5000 COMMENT '我方向对方调用 verify 接口时的超时时间,单位毫秒',
    `verify_retry_count`              INT NOT NULL DEFAULT 0 COMMENT '我方向对方调用 verify 失败后的最大重试次数。0 表示失败即结束,不重试',
    `verify_retry_interval_ms`        INT NOT NULL DEFAULT 0 COMMENT 'verify 重试间隔,单位毫秒。只有 verify_retry_count > 0 时才有意义',

    `ip_allow_list`                   VARCHAR(2000) DEFAULT NULL COMMENT '来源 IP 白名单,多个以英文逗号分隔。为空表示不限制。用于限制谁可以调用我方 getTokenBySso / verify',
    `status`                          TINYINT NOT NULL DEFAULT 1 COMMENT '记录状态:0-停用,1-启用。停用后不允许换token、不允许 verify、不允许业务交互',

    `oa_connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '最近一次连通性测试快照:0-未测试,1-成功,2-失败',
    `oa_connect_env`                  VARCHAR(20) DEFAULT NULL COMMENT '最近一次测试环境:TEST/PRODUCTION',
    `oa_connect_test_type`            VARCHAR(30) DEFAULT NULL COMMENT '最近一次测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token链路测试',
    `oa_connect_time`                 DATETIME DEFAULT NULL COMMENT '最近一次点击“连通对方OA”或系统自动连通性检测的时间',
    `oa_connect_result_code`          VARCHAR(64) DEFAULT NULL COMMENT '最近一次连通性测试结果码,例如 SUCCESS、TIMEOUT、HTTP_403、VERIFY_FAIL、DNS_ERROR',
    `oa_connect_result_msg`           VARCHAR(1000) DEFAULT NULL COMMENT '最近一次连通性测试结果说明',
    `oa_connect_response_time_ms`     INT DEFAULT NULL COMMENT '最近一次连通性测试总耗时,单位毫秒',

    `remark`                          VARCHAR(1000) DEFAULT NULL COMMENT '备注。可记录该企业的特殊对接约定、异常说明、上线注意事项',
    `created_by`                      BIGINT DEFAULT NULL COMMENT '创建人',
    `updated_by`                      BIGINT DEFAULT NULL COMMENT '更新人',
    `is_deleted`                      TINYINT NOT NULL DEFAULT 0 COMMENT '是否逻辑删除:0否,1是',
    `deleted_time`                    DATETIME DEFAULT NULL COMMENT '逻辑删除时间',
    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_tenant_id` (`tenant_id`) USING BTREE,
    UNIQUE KEY `uk_partner_code` (`partner_code`) USING BTREE,
    UNIQUE KEY `uk_enterprise_code` (`enterprise_code`) USING BTREE,

    KEY `idx_partner_name` (`partner_name`) USING BTREE,
    KEY `idx_status` (`status`) USING BTREE,
    KEY `idx_deploy_mode` (`deploy_mode`) USING BTREE,
    KEY `idx_partner_expire_time` (`partner_expire_time`) USING BTREE,
    KEY `idx_oa_connect_status` (`oa_connect_status`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='对接企业主表(新 SSO/JWT 模式主配置表,一个 partner 即一家企业)';


-- =========================================================
-- 对方 OA / SSO 接口连通性测试日志表
--
-- 设计定位:
-- 1)记录每次点击“连通对方OA”的历史
-- 2)记录测试的是基础地址、verify 接口,还是完整 getTokenBySso 链路
-- 3)bridge_partner 只留最新快照,本表保留全量历史
--
-- 最小必要原则说明:
-- 1)保留关键请求目标、耗时、结果码、结果说明
-- 2)不保留过多过程冗余字段
-- =========================================================
DROP TABLE IF EXISTS `bridge_partner_connectivity_log`;
CREATE TABLE `bridge_partner_connectivity_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',
    `enterprise_code`              VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码,冗余保存便于按信用代码直接检索',
    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',

    `connect_env`                  VARCHAR(20) NOT NULL COMMENT '测试环境:TEST/PRODUCTION',
    `deploy_mode`                  VARCHAR(20) DEFAULT NULL COMMENT '本次测试使用的部署模式:CLOUD/SELFBUILT',
    `test_type`                    VARCHAR(30) NOT NULL COMMENT '测试类型:HOST_PING-基础地址探测;VERIFY_API-verify接口探测;TOKEN_EXCHANGE-完整换token测试',
    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次实际请求的完整 URL',
    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,例如 GET/POST',

    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '本次测试请求流水号。用于串联应用日志',
    `request_body`                 JSON DEFAULT NULL COMMENT '请求报文。建议只保留必要字段,避免敏感信息直接明文落库',
    `response_body`                JSON DEFAULT NULL COMMENT '响应报文。建议只保留关键字段,例如 code、msg、success',

    `connect_status`               TINYINT NOT NULL DEFAULT 0 COMMENT '测试结果:0失败,1成功',
    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '结果码:SUCCESS、TIMEOUT、DNS_ERROR、SSL_ERROR、HTTP_403、HTTP_500、VERIFY_FAIL 等',
    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '结果说明,例如“DNS解析失败”“verify接口返回业务失败”',
    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP 状态码。若请求未成功发出,可为空',
    `response_time_ms`             INT DEFAULT NULL COMMENT '本次测试总耗时,单位毫秒',

    `operator_id`                  BIGINT DEFAULT NULL COMMENT '操作人ID。若为系统自动探测可为空',
    `operator_name`                VARCHAR(100) DEFAULT NULL COMMENT '操作人姓名。若为系统自动探测可写 SYSTEM',
    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '操作来源IP',
    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_connect_env` (`connect_env`) USING BTREE,
    KEY `idx_test_type` (`test_type`) USING BTREE,
    KEY `idx_connect_status` (`connect_status`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='对方OA与SSO接口连通性测试日志表';


-- =========================================================
-- SSO/JWT 换 token 主日志表
--
-- 这是最核心的一张主流水表。
--
-- 这张表既记录“对方调我方 getTokenBySso”,也记录“我方调对方 getTokenBySso”。
-- 通过 exchange_direction 区分方向:
--
-- 1)INBOUND:
--    对方系统调用我方 /api/oauth/getTokenBySso
--    也就是“对方拿 encryption 来换我方 token”
--
-- 2)OUTBOUND:
--    我方系统调用对方 /api/oauth/getTokenBySso
--    也就是“我方向对方提交 encryption,换取对方 token”
--
-- 因此,表中部分字段的含义会随方向变化:
--
-- request_url:
-- - INBOUND:对方调到我方的 getTokenBySso 接口地址
-- - OUTBOUND:我方实际调用对方的 getTokenBySso 完整地址
--
-- source_ip:
-- - INBOUND:对方请求打到我方时的来源IP
-- - OUTBOUND:通常为空,或记录我方本机/出口IP(若业务侧有需要)
--
-- request_body:
-- - INBOUND:对方请求我方时提交的原始 body
-- - OUTBOUND:我方向对方发出的原始 body
--
-- request_thirdparty / request_module / partner_tenant_id / request_enterprise_code /
-- request_expire_time / request_nonce:
-- - 无论 INBOUND 还是 OUTBOUND,都是“本次换 token 所使用的 encryption 内解析出的字段”
--
-- verify_status:
-- - 指“我方是否已经向对方 verify 接口发起验证,并最终得到通过结果”
-- - 无论 INBOUND 还是 OUTBOUND,只要当前流程需要我方去调对方 verify,都记录在这里
--
-- token_issue_status:
-- - INBOUND:我方是否成功签发了自己的 access_token 给对方
-- - OUTBOUND:对方是否成功签发了 token 给我方;我方在收到对方响应并保存成功后,标记为成功
--
-- 关于 clock_skew_seconds 计算方式:
-- 1)当 encryption 中带有 expireTime(Unix时间戳)时,先转成请求声明过期时间 request_expire_time
-- 2)以“我方收到请求或发起请求时的当前服务器时间 current_time”为基准
-- 3)可按如下方式计算:
--    clock_skew_seconds = unix_timestamp(current_time) - unix_timestamp(request_expire_time)
-- 4)解释:
--    - 小于 0:说明距离过期还有多少秒
--    - 等于 0:说明刚好到期
--    - 大于 0:说明已超过 expireTime 多少秒
-- 5)业务判断时通常不是简单要求 <= 0,而是:
--    clock_skew_seconds <= allowed_clock_skew_seconds
--    这样就能兼容双方服务器时间轻微不一致
--
-- 最小必要原则说明:
-- 1)不再额外冗余 partner_name 等可随时从主表拿到的字段
-- 2)保留 enterprise_code / partner_code,是为了日志检索和问题定位时少连表
-- =========================================================
DROP TABLE IF EXISTS `bridge_sso_exchange_log`;
CREATE TABLE `bridge_sso_exchange_log`
(
    `id`                              BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `request_id`                      VARCHAR(100) NOT NULL COMMENT '本次换token请求流水号,建议全局唯一。用于串联应用日志、verify日志、token日志',
    `tenant_id`                       BIGINT DEFAULT NULL COMMENT '匹配到的我方企业唯一编码。若在早期校验阶段失败,尚未匹配成功,则可为空',
    `enterprise_code`                 VARCHAR(100) DEFAULT NULL COMMENT '最终识别到的企业统一社会信用代码。通常来自 encryption.creditCode 或 partner 映射结果',
    `partner_id`                      BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id。若尚未匹配成功,可为空',
    `partner_code`                    VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余,便于不连表直接检索',

    `exchange_direction`              VARCHAR(20) NOT NULL DEFAULT 'INBOUND' COMMENT '换token方向:INBOUND-对方调我方 getTokenBySso;OUTBOUND-我方调对方 getTokenBySso',
    `exchange_env`                    VARCHAR(20) DEFAULT NULL COMMENT '执行环境:TEST/PRODUCTION',
    `deploy_mode`                     VARCHAR(20) DEFAULT NULL COMMENT '本次请求中的模式:CLOUD/SELFBUILT。优先取 encryption.module;若没有再回落 partner 默认配置',

    `source_ip`                       VARCHAR(50) DEFAULT NULL COMMENT '来源IP。INBOUND 时表示对方请求打到我方的来源IP;OUTBOUND 时通常为空或按需记录我方出口IP',
    `http_method`                     VARCHAR(20) DEFAULT NULL COMMENT '本次换token接口请求方式,通常为 POST',
    `request_url`                     VARCHAR(1000) DEFAULT NULL COMMENT '请求命中的接口URL。INBOUND 时是我方 getTokenBySso 地址;OUTBOUND 时是对方 getTokenBySso 地址',
    `request_body`                    JSON DEFAULT NULL COMMENT '原始请求体。INBOUND 时是对方发给我方的 body;OUTBOUND 时是我方向对方发出的 body。建议仅保留必要字段',

    `encryption_preview`              VARCHAR(500) DEFAULT NULL COMMENT '本次请求中 encryption 的脱敏预览值,例如前30位...后20位,便于人工排查',
    `encryption_hash`                 VARCHAR(255) DEFAULT NULL COMMENT 'encryption 摘要值。用于去重、追踪、防重复排查,不直接暴露原文',
    `encryption_ciphertext`           TEXT DEFAULT NULL COMMENT 'encryption 留存值。建议存加密后的密文,而不是直接裸存原文。用于满足审计、追溯、问题复盘场景',

    `jwt_alg`                         VARCHAR(30) DEFAULT NULL COMMENT '从 encryption 的 JWT 头部解析出的算法标识',
    `jwt_issuer`                      VARCHAR(200) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 iss。若无则为空',
    `jwt_audience`                    VARCHAR(200) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 aud。若无则为空',
    `jwt_jti`                         VARCHAR(100) DEFAULT NULL COMMENT '从 encryption claim 中解析出的 jti。若协议未使用可为空',

    `request_thirdparty`              VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 thirdparty,例如 zhipingyun、nuoming',
    `request_module`                  VARCHAR(20) DEFAULT NULL COMMENT '从 encryption 中解析出的 module,通常为 CLOUD/SELFBUILT',
    `partner_tenant_id`               VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 tenantId。这里是“请求发起方在其自身系统中的租户ID”,保留字符串以兼容非纯数字编码',
    `request_enterprise_code`         VARCHAR(100) DEFAULT NULL COMMENT '从 encryption 中解析出的 creditCode 原值',
    `request_expire_time`             DATETIME DEFAULT NULL COMMENT '从 encryption 中解析出的 expireTime,对应该次请求票据自身的过期时间,不是 access_token 过期时间',
    `request_nonce`                   VARCHAR(200) DEFAULT NULL COMMENT '从 encryption 中解析出的 nonce,用于防重放',

    `parse_status`                    TINYINT NOT NULL DEFAULT 0 COMMENT 'encryption 解析结果:0失败,1成功',
    `parse_result_code`               VARCHAR(64) DEFAULT NULL COMMENT '解析结果码:SUCCESS、ENCRYPTION_EMPTY、JWT_FORMAT_INVALID、JWT_DECODE_FAIL、JWT_HEADER_INVALID、JWT_CLAIM_INVALID 等',
    `parse_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT '解析结果说明',

    `claim_validate_status`           TINYINT NOT NULL DEFAULT 0 COMMENT 'claim 基础校验结果:0失败,1成功',
    `claim_validate_code`             VARCHAR(64) DEFAULT NULL COMMENT 'claim 校验结果码:SUCCESS、PARTNER_NOT_FOUND、ENTERPRISE_CODE_MISMATCH、THIRDPARTY_MISMATCH、MODULE_INVALID、JWT_EXPIRED、CLOCK_SKEW_INVALID、IP_DENIED、PARTNER_DISABLED、PARTNER_EXPIRED 等',
    `claim_validate_msg`              VARCHAR(1000) DEFAULT NULL COMMENT 'claim 基础校验结果说明',
    `clock_skew_seconds`              INT DEFAULT NULL COMMENT '服务端计算出的时间偏差秒数。建议按“当前服务器时间戳 - request_expire_time时间戳”计算;小于0表示距离过期还有多少秒,大于0表示已超出多少秒',
    
    `nonce_check_status`              TINYINT NOT NULL DEFAULT 0 COMMENT 'nonce 校验结果:0未校验或失败,1成功',
    `nonce_check_code`                VARCHAR(64) DEFAULT NULL COMMENT 'nonce 校验结果码:SUCCESS、NONCE_MISSING、NONCE_REPLAY、NONCE_EXPIRED、NONCE_INVALID 等',
    `nonce_check_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT 'nonce 校验结果说明',

    `verify_status`                   TINYINT NOT NULL DEFAULT 0 COMMENT '我方调用对方 verify 接口后的最终验证结果:0失败,1成功。注意:这里只记录“我方去调对方 verify”的结果,不记录“对方调我方 verify”的入站情况',
    `verify_result_code`              VARCHAR(64) DEFAULT NULL COMMENT 'verify 最终结果码:SUCCESS、VERIFY_API_TIMEOUT、VERIFY_HTTP_FAIL、VERIFY_RESPONSE_INVALID、VERIFY_BUSINESS_REJECT 等',
    `verify_result_msg`               VARCHAR(1000) DEFAULT NULL COMMENT 'verify 最终结果说明',
    `verify_attempt_count`            INT NOT NULL DEFAULT 0 COMMENT '本次换token流程中,我方对对方 verify 接口总共尝试调用了多少次,包括重试次数',
    `verify_success_time`             DATETIME DEFAULT NULL COMMENT 'verify 最终成功时间。未成功则为空',

    `token_issue_status`              TINYINT NOT NULL DEFAULT 0 COMMENT 'token 签发/获取结果:INBOUND 时表示我方是否成功签发 token 给对方;OUTBOUND 时表示我方是否成功从对方获取并保存 token',
    `token_issue_code`                VARCHAR(64) DEFAULT NULL COMMENT '签发/获取结果码:SUCCESS、VERIFY_NOT_PASS、TOKEN_GENERATE_FAIL、TOKEN_SAVE_FAIL、PARTNER_DISABLED、REMOTE_TOKEN_ISSUE_FAIL 等',
    `token_issue_msg`                 VARCHAR(1000) DEFAULT NULL COMMENT '签发/获取结果说明',
    `issued_token_log_id`             BIGINT DEFAULT NULL COMMENT '若成功保存 token,对应 bridge_access_token_log.id,便于回查',
    `issued_expire_time`              DATETIME DEFAULT NULL COMMENT '本次最终得到的 access_token 过期时间。INBOUND 时是我方签发给对方的 token 过期时间;OUTBOUND 时是对方签发给我方的 token 过期时间',

    `final_status`                    VARCHAR(30) NOT NULL DEFAULT 'PROCESSING' COMMENT '整条换token链路最终状态:PROCESSING处理中;SUCCESS成功;FAILED失败',
    `final_result_code`               VARCHAR(64) DEFAULT NULL COMMENT '整条链路最终结果码。通常可直接作为统计报表口径',
    `final_result_msg`                VARCHAR(1000) DEFAULT NULL COMMENT '整条链路最终结果说明',
    `finished_time`                   DATETIME DEFAULT NULL COMMENT '整条链路完成时间。无论成功还是失败,只要流程结束就应写入',

    `create_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                     DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,
    KEY `idx_request_nonce` (`request_nonce`) USING BTREE,
    KEY `idx_jwt_jti` (`jwt_jti`) USING BTREE,
    KEY `idx_encryption_hash` (`encryption_hash`) USING BTREE,
    KEY `idx_verify_status` (`verify_status`) USING BTREE,
    KEY `idx_token_issue_status` (`token_issue_status`) USING BTREE,
    KEY `idx_final_status` (`final_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='SSO/JWT 换 token 主日志表';


-- =========================================================
-- 我方调用对方 verify 接口明细日志表
--
-- 设计定位:
-- 1)一次换token流程中,我方可能会多次调用对方 verify(例如超时后重试)
-- 2)bridge_sso_exchange_log 只保留 verify 最终结果和尝试次数
-- 3)本表保留每一次“我方调对方 verify”的明细
--
-- 重要说明:
-- 1)本表不是“对方调我方 verify”的日志
-- 2)“对方调我方 verify”的记录,单独放在 bridge_sso_verify_receive_log
-- =========================================================
DROP TABLE IF EXISTS `bridge_sso_verify_log`;
CREATE TABLE `bridge_sso_verify_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `exchange_log_id`              BIGINT NOT NULL COMMENT '关联 bridge_sso_exchange_log.id',
    `request_id`                   VARCHAR(100) NOT NULL COMMENT '换token主请求流水号冗余,便于不连表排查',

    `tenant_id`                    BIGINT DEFAULT NULL COMMENT '企业唯一编码。若请求在早期失败,尚未匹配成功,可为空',
    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '企业统一社会信用代码冗余',
    `partner_id`                   BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id',
    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',

    `verify_env`                   VARCHAR(20) DEFAULT NULL COMMENT '调用环境:TEST/PRODUCTION',
    `deploy_mode`                  VARCHAR(20) DEFAULT NULL COMMENT '本次 verify 使用的部署模式:CLOUD/SELFBUILT',
    `attempt_no`                   INT NOT NULL COMMENT '第几次调用,从1开始递增',
    `target_url`                   VARCHAR(1000) DEFAULT NULL COMMENT '本次调用对方 verify 的完整 URL',
    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,通常为 POST',

    `request_thirdparty`           VARCHAR(100) DEFAULT NULL COMMENT '本次请求对方 verify 时提交的 thirdparty 值',
    `request_encryption_preview`   VARCHAR(500) DEFAULT NULL COMMENT '本次提交给对方 verify 的 encryption 脱敏预览值',
    `request_encryption_hash`      VARCHAR(255) DEFAULT NULL COMMENT '本次提交给对方 verify 的 encryption 摘要值',
    `request_nonce`                VARCHAR(200) DEFAULT NULL COMMENT '本次请求关联的 nonce',
    `request_body`                 JSON DEFAULT NULL COMMENT '本次调用对方 verify 的请求报文。建议只保留必要字段',
    `response_body`                JSON DEFAULT NULL COMMENT '本次调用对方 verify 的响应报文。建议只保留 success、error 等关键字段',

    `call_status`                  TINYINT NOT NULL DEFAULT 0 COMMENT '本次调用是否成功拿到“可解析响应”:0失败,1成功',
    `result_code`                  VARCHAR(64) DEFAULT NULL COMMENT '调用层结果码:SUCCESS、TIMEOUT、CONNECT_FAIL、HTTP_403、HTTP_500、RESPONSE_INVALID、BUSINESS_REJECT 等',
    `result_msg`                   VARCHAR(1000) DEFAULT NULL COMMENT '调用层结果说明',
    `http_status_code`             INT DEFAULT NULL COMMENT 'HTTP 状态码。若请求未成功发出,可为空',

    `business_verify_status`       TINYINT DEFAULT NULL COMMENT '对方业务层验签结果:0失败,1成功。只有拿到业务响应时才有意义',
    `business_verify_code`         VARCHAR(64) DEFAULT NULL COMMENT '对方业务层结果码,例如 SUCCESS、SIGN_INVALID、JWT_EXPIRED、NONCE_INVALID 等',
    `business_verify_msg`          VARCHAR(1000) DEFAULT NULL COMMENT '对方业务层结果说明',
    `response_time_ms`             INT DEFAULT NULL COMMENT '本次 verify 调用耗时,单位毫秒',

    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`) USING BTREE,
    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_attempt_no` (`attempt_no`) USING BTREE,
    KEY `idx_call_status` (`call_status`) USING BTREE,
    KEY `idx_business_verify_status` (`business_verify_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='我方调用对方 verify 接口明细日志表';


-- =========================================================
-- 对方调用我方 verify 接口接收日志表
--
-- 设计原因:
-- 1)你特别问到了:“他调用我的 verify 记录在哪里?”
-- 2)原来的几张表里,这部分并没有单独落地
-- 3)这张表就是专门记录“对方调我方 /api/oauth/verify”的入站日志
--
-- 为什么这张表是必要表:
-- 1)verify 是安全关键接口,不建议完全不留入站审计
-- 2)若没有这张表,后续很难回答:
--    - 谁调用过我方 verify
--    - 调了多少次
--    - 带了什么 thirdparty / encryption
--    - 为什么校验失败
-- 3)因此它不是过度设计,而是安全审计上的最小必要补充
-- =========================================================
DROP TABLE IF EXISTS `bridge_sso_verify_receive_log`;
CREATE TABLE `bridge_sso_verify_receive_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `request_id`                   VARCHAR(100) NOT NULL COMMENT '本次我方 verify 入站请求流水号,建议全局唯一',
    `tenant_id`                    BIGINT DEFAULT NULL COMMENT '匹配到的我方企业唯一编码。若尚未匹配成功,可为空',
    `enterprise_code`              VARCHAR(100) DEFAULT NULL COMMENT '最终识别到的企业统一社会信用代码',
    `partner_id`                   BIGINT DEFAULT NULL COMMENT '关联 bridge_partner.id。若尚未匹配成功,可为空',
    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余,便于不连表检索',

    `verify_env`                   VARCHAR(20) DEFAULT NULL COMMENT '执行环境:TEST/PRODUCTION',
    `deploy_mode`                  VARCHAR(20) DEFAULT NULL COMMENT '本次请求中的模式:CLOUD/SELFBUILT',
    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '对方调用我方 verify 时的来源IP',
    `http_method`                  VARCHAR(20) DEFAULT NULL COMMENT '请求方式,通常为 POST',
    `request_url`                  VARCHAR(1000) DEFAULT NULL COMMENT '对方请求命中的我方 verify 接口 URL',
    `request_body`                 JSON DEFAULT NULL COMMENT '对方发给我方 verify 的原始请求体。建议仅保留必要字段',

    `request_thirdparty`           VARCHAR(100) DEFAULT NULL COMMENT '对方传给我方 verify 的 thirdparty',
    `encryption_preview`           VARCHAR(500) DEFAULT NULL COMMENT '对方传给我方 verify 的 encryption 脱敏预览值',
    `encryption_hash`              VARCHAR(255) DEFAULT NULL COMMENT '对方传给我方 verify 的 encryption 摘要值',
    `request_nonce`                VARCHAR(200) DEFAULT NULL COMMENT '从 encryption 中解析出的 nonce。若解析失败可为空',

    `parse_status`                 TINYINT NOT NULL DEFAULT 0 COMMENT 'encryption 解析结果:0失败,1成功',
    `parse_result_code`            VARCHAR(64) DEFAULT NULL COMMENT '解析结果码:SUCCESS、ENCRYPTION_EMPTY、JWT_FORMAT_INVALID、JWT_DECODE_FAIL、JWT_CLAIM_INVALID 等',
    `parse_result_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '解析结果说明',

    `exists_check_status`          TINYINT NOT NULL DEFAULT 0 COMMENT '服务端签发存在性校验结果:0失败,1成功。用于回答“这个 encryption 是否确实由我方服务端签发过”',
    `exists_check_code`            VARCHAR(64) DEFAULT NULL COMMENT '存在性校验结果码:SUCCESS、NOT_FOUND、EXPIRED、REVOKED、THIRDPARTY_MISMATCH、NONCE_MISMATCH 等',
    `exists_check_msg`             VARCHAR(1000) DEFAULT NULL COMMENT '存在性校验结果说明',

    `response_success`             TINYINT NOT NULL DEFAULT 0 COMMENT '我方 verify 接口最终是否返回成功:0否,1是',
    `response_body`                JSON DEFAULT NULL COMMENT '我方 verify 接口返回给对方的响应报文。建议仅保留 success、error 等关键字段',
    `http_status_code`             INT DEFAULT NULL COMMENT '我方 verify 接口返回的 HTTP 状态码',
    `response_time_ms`             INT DEFAULT NULL COMMENT '本次 verify 入站请求处理耗时,单位毫秒',

    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,
    KEY `idx_encryption_hash` (`encryption_hash`) USING BTREE,
    KEY `idx_request_nonce` (`request_nonce`) USING BTREE,
    KEY `idx_exists_check_status` (`exists_check_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='对方调用我方 verify 接口接收日志表';


-- =========================================================
-- access_token 签发与状态日志表
--
-- 说明:
-- 1)当前 access_token 的来源不再是 app_key/app_secret
-- 2)而是 encryption + verify 成功之后的签发结果
-- 3)本表用于记录 token 的签发、有效、过期、吊销状态
--
-- 最小必要原则说明:
-- 1)不再冗余 partner_name
-- 2)优先保留 token_hash + token_preview
-- 3)token 明文仅在当前排障阶段短期保留,后续建议收紧
-- =========================================================
DROP TABLE IF EXISTS `bridge_access_token_log`;
CREATE TABLE `bridge_access_token_log`
(
    `id`                           BIGINT NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    `exchange_log_id`              BIGINT DEFAULT NULL COMMENT '关联 bridge_sso_exchange_log.id。表示该 token 来源于哪次换 token 流程',
    `request_id`                   VARCHAR(100) DEFAULT NULL COMMENT '换token请求流水号冗余,便于不连表排查',

    `tenant_id`                    BIGINT NOT NULL COMMENT '企业唯一编码',
    `enterprise_code`              VARCHAR(100) NOT NULL COMMENT '企业统一社会信用代码',
    `partner_id`                   BIGINT NOT NULL COMMENT '关联 bridge_partner.id',
    `partner_code`                 VARCHAR(100) DEFAULT NULL COMMENT '对接企业编码冗余',

    `grant_type`                   VARCHAR(50) NOT NULL DEFAULT 'sso_jwt_exchange' COMMENT '授权来源类型。当前固定为 sso_jwt_exchange,表示由 SSO/JWT 换 token 流程签发',
    `token_jti`                    VARCHAR(100) NOT NULL COMMENT '我方签发或保存的 access_token 唯一编号。建议全局唯一,例如 lower(replace(uuid(), ''-'', ''''))',
    `token`                        VARCHAR(2048) DEFAULT NULL COMMENT 'access_token 明文。当前如为排障方便可保留;后续建议关闭明文落库',
    `token_hash`                   VARCHAR(255) DEFAULT NULL COMMENT 'access_token 摘要值。用于追踪、校验,不暴露明文',
    `token_preview`                VARCHAR(200) DEFAULT NULL COMMENT 'access_token 脱敏预览值,例如前20位...后10位',

    `issued_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '签发或保存时间',
    `effective_time`               DATETIME DEFAULT NULL COMMENT '生效时间。通常等于签发时间;若将来有延迟生效需求,可单独记录',
    `expire_time`                  DATETIME NOT NULL COMMENT '过期时间',
    `token_status`                 TINYINT NOT NULL DEFAULT 1 COMMENT 'token 状态:0失效,1有效,2已吊销',
    `revoke_time`                  DATETIME DEFAULT NULL COMMENT '吊销时间',
    `revoke_reason`                VARCHAR(500) DEFAULT NULL COMMENT '吊销原因,例如企业停用、安全事件、人工禁用',

    `source_ip`                    VARCHAR(50) DEFAULT NULL COMMENT '触发签发或保存时的来源IP',
    `create_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time`                  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',

    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `uk_token_jti` (`token_jti`) USING BTREE,
    KEY `idx_exchange_log_id` (`exchange_log_id`) USING BTREE,
    KEY `idx_request_id` (`request_id`) USING BTREE,
    KEY `idx_partner_id` (`partner_id`) USING BTREE,
    KEY `idx_tenant_id` (`tenant_id`) USING BTREE,
    KEY `idx_enterprise_code` (`enterprise_code`) USING BTREE,
    KEY `idx_expire_time` (`expire_time`) USING BTREE,
    KEY `idx_token_status` (`token_status`) USING BTREE,
    KEY `idx_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB
  DEFAULT CHARSET=utf8mb4
  COLLATE=utf8mb4_0900_ai_ci COMMENT='access_token 签发与状态日志表(来源于 SSO/JWT 换 token)';

SET FOREIGN_KEY_CHECKS = 1;

我问:

除了以上表之后,对方签发给我方的token没有日志么?请你核实一下,如果有,指出哪个表即可,如果没有,请你补充完整,再输出完整sql。

AI答:

有。

对应的就是这张表:

bridge_access_token_log

它并不只记录“我方签发给对方的 token”,也记录“对方签发给我方、并被我方接收/保存下来的 token”。

你前一版 SQL 里,这个含义已经体现在这些注释里:

exchange_log_id:表示该 token 来源于哪次换 token 流程
grant_type:来源于 sso_jwt_exchange
token_jti:我方签发或保存的 access_token 唯一编号
token:access_token 明文
issued_time:签发或保存时间

再结合 bridge_sso_exchange_log 里的这几个字段一起看,逻辑就是完整的:

exchange_direction='INBOUND'
表示对方调我方,最终是我方签发 token 给对方

exchange_direction='OUTBOUND'
表示我方调对方,最终是对方签发 token 给我方,而我方把这个 token 保存到 bridge_access_token_log

也就是说:

对方签发给我方的 token
不是没有日志
而是已经落在 bridge_access_token_log 里了

如果你想让语义更直白,后续可以把 bridge_access_token_log 里再补一个字段,例如:

token_owner_sidetoken_source_side

用于明确区分:
LOCAL_ISSUED:我方签发
REMOTE_ISSUED:对方签发

但从“最小必要原则”来说,当前这套其实已经够了,因为已经可以通过:

bridge_sso_exchange_log.exchange_direction

来判断这条 token 是哪一边签发的。

我问:

你前面说到的接口探测是先得有token测试完了才能请求某个街口吧?基础探测是不是直接拿host测试其连通性,回答我是/否,简单解释即可。

AI答:

是。

简单分两层:

1)基础探测(HOST_PING)

是的,就是只测试 host 连通性
例如:

  • DNS 是否能解析

  • TCP/HTTPS 是否能建立连接

  • 是否能返回 HTTP 响应(哪怕是 404)

通常做法:

GET https://api.xxx.com

或者

HEAD https://api.xxx.com

只要:

  • 能建立连接

  • 能返回 HTTP 状态

就算 连通成功

它的作用只是判断:

网络通不通、域名对不对、SSL 是否正常

不涉及 token

2)接口探测(VERIFY_API / TOKEN_EXCHANGE)

这一步才是:

  • 调 verify

  • 调 getTokenBySso

  • 或调用某个业务接口

这里通常才需要:

  • encryption

  • 或 token

所以流程一般是:

HOST_PING
   ↓
VERIFY_API
   ↓
TOKEN_EXCHANGE
   ↓
业务接口

总结一句话:

基础探测只测 host 网络连通性,不需要 token。
接口探测才会走认证逻辑。

我问:


我跟他进行鉴权的时候我的thirdparty,module,tenantId,creditCode,expireTime,nonce也记录在bridge_sso_exchange_log表中吧?请你回答是/否,简要说明。

AI答:

是。

简要说明:

bridge_sso_exchange_log 记录的是一次完整的 SSO 换 token 主流程日志,其中会解析并落库 encryption(JWT)中的关键字段,因此会记录:

JWT字段表字段
thirdpartyrequest_thirdparty
modulerequest_module
tenantIdpartner_tenant_id
creditCoderequest_enterprise_code
expireTimerequest_expire_time
noncerequest_nonce

记录这些字段的目的:

  1. 排查问题
    能快速知道对方当时传了什么参数。

  2. 安全审计
    例如追查 nonce 重放、过期时间异常等。

  3. 减少反复解析 JWT
    关键字段直接落库,后续查询日志无需再次解密。

同时不会只存原文 encryption,还会存:

  • encryption_preview(脱敏)

  • encryption_hash(摘要)

这样既能排查问题,也避免敏感信息直接明文长期存储。

我问:

我的意思是,我请求他的时候,我方进行加密的这些字段,是否也存在这里。

AI答:

是。

简要说明:

我方请求对方换 token(OUTBOUND 场景) 时,
我方生成的 encryption(JWT)里包含的这些字段:

  • thirdparty

  • module

  • tenantId

  • creditCode

  • expireTime

  • nonce

也会被解析并记录到 bridge_sso_exchange_log 中。

原因是:

bridge_sso_exchange_log 设计为 双向主流水日志表,记录两种情况:

1️⃣ INBOUND
对方调用我方 /getTokenBySso

2️⃣ OUTBOUND
我方调用对方 /getTokenBySso

无论是哪种方向,系统都会:

  • 解析 encryption

  • 把里面的关键字段落库

因此:

encryption字段bridge_sso_exchange_log字段
thirdpartyrequest_thirdparty
modulerequest_module
tenantIdpartner_tenant_id
creditCoderequest_enterprise_code
expireTimerequest_expire_time
noncerequest_nonce

这样做的目的:

  • 排查双方对接问题

  • 安全审计(nonce、防重放)

  • 无需再次解密JWT即可查看请求参数

我问:

    `verify_status`                   TINYINT NOT NULL DEFAULT 0 COMMENT '我方调用对方 verify 接口后的最终验证结果:0失败,1成功。注意:这里只记录“我方去调对方 verify”的结果,不记录“对方调我方 verify”的入站情况',


这个既然只记录我调取对方,默认不能为null,我记录啥呢?请简要回答。

AI答:

简要回答:

默认记录为 0(未通过/未执行)。

原因:

bridge_sso_exchange_log 中:

  • INBOUND 场景(对方调我方换 token)
    我方需要调用对方 /verify,因此最终会更新为:

    • 1:verify 成功

    • 0:verify 失败

  • OUTBOUND 场景(我方调对方换 token)
    我方通常不需要再调对方 verify(因为对方会调我方 verify),
    因此这个字段会保持默认值 0

换句话说:

场景verify_status
INBOUND 且 verify 成功1
INBOUND 且 verify 失败0
OUTBOUND(我方不调 verify)0(保持默认)

如果想语义更清晰,理论上可以设计为:

0 未执行
1 成功
2 失败

但在你当前“最小必要原则”的设计下,默认 0 直接表示未执行或失败即可。