mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-10 02:20:28 +08:00
7af83b089e
Architecture audit revealed AuthProvider (8 methods) only covers ~15% of BitAnswer's 50+ C API surface. This spec proposes: - 6 capability interfaces (LicenseLifecycle, FeatureManagement, DataItemStore, LicenseInfoQuery, CheckoutManager, LicenseUtility) - 40+ JNI → Rust → BitAnswer C API mappings - 4-phase migration path with backward compatibility
17 KiB
17 KiB
BitAnswer 1:1 映射重构设计
状态: 待审核
日期: 2026-05-01
触发: 架构审计发现AuthProvider(8 方法) 与 BitAnswer C API (50+ 函数) 之间存在显著缺口
策略: 大幅重构为 BitAnswer 1:1 原语映射,按能力域拆分接口
1. 审计摘要
1.1 当前状态
Java AuthProvider (8 methods)
└─ BitAnswerProvider / SelfHostedAuthProvider
└─ NativeBridge (JNI, 9 native methods)
└─ craft-core cdylib (Rust, 9 craft_* C ABI functions)
└─ ⚠️ 全部返回 ok_result(桩实现,未调用真实 BitAnswer API)
└─ [已废弃] .deprecated-cmake/ bitanswer_adapter(空实现)
1.2 覆盖度缺口
| BitAnswer API 分组 | 原生函数数 | 当前覆盖 | 缺失 |
|---|---|---|---|
| 认证与会话 | 10+ | 3 (activate/release/close) | LoginEx, LoginByToken, Revoke, RemoveSn, SessionControl |
| 激活与升级 | 6 | 1 (activate) | 离线升级三步骤 |
| 特征项 | 15+ | 1 (hasFeature) | Read/Write/Query/Release/Encrypt/Decrypt/Convert/Sign/Batch |
| 配置项(Data) | 5 | 0 | Set/Get/Remove/Enum |
| 借出/归还 | 9 | 0 | CheckOut/In, Borrow |
| 信息查询 | 5+ | 1 (getLicenseInfo) | SessionInfo, ServerInfo, FeatureInfo |
| 工具类 | 8+ | 0 | SetRootPath, SetProxy, SetAttr, CustomInfo |
2. 目标架构
2.1 接口分层(6 能力接口 + 1 入口)
CraftLicense (顶层入口)
- initialize(configJson) → LicenseSession
- getVersion() → String
- setRootPath(path) / setProxy(...) / setLocalServer(...)
LicenseSession (会话句柄,实现 5 个能力接口)
├─ LicenseLifecycle — 认证/激活/心跳/释放
├─ FeatureManagement — 特征项读写/加解密/占用释放
├─ DataItemStore — 配置项(Data Item)存储
├─ LicenseInfoQuery — 信息查询
├─ CheckoutManager — 浮动授权借出/归还
├─ LicenseUtility — 工具方法(SetAttr, CustomInfo, SessionState)
└─ close() / isClosed() / getNativeHandle()
2.2 能力接口详细定义
LicenseLifecycle
public interface LicenseLifecycle {
LoginResult login(LoginRequest request);
LoginResult loginEx(LoginExRequest request);
LoginResult loginByToken(LoginByTokenRequest request);
LoginResult loginByPassword(LoginByPasswordRequest request);
ActivationResult activate(ActivationRequest request);
UpdateResult updateOnline(String url, String sn);
OfflineUpdateRequest getRequestInfo(String sn, BindingType type);
UpdateInfo getUpdateInfo(String url, String sn, String requestInfo);
ApplyResult applyUpdateInfo(String updateInfo);
HeartbeatResult heartbeat();
ReleaseResult release();
RevokeResult revoke(String sn);
void removeSn(String sn);
void sessionControl(String url, String sessionId, SessionCtlType type);
}
FeatureManagement
public interface FeatureManagement {
int readFeature(int featureId);
void writeFeature(int featureId, int value);
int convertFeature(int featureId, int p1, int p2, int p3, int p4);
byte[] encryptFeature(int featureId, byte[] plainData);
byte[] decryptFeature(int featureId, byte[] cipherData);
int queryFeature(int featureId);
int queryFeatureEx(int featureId, QueryMode mode, int required, String scope);
Ticket queryFeatureEx2(String featureName, QueryMode mode, int required, String scope);
int releaseFeature(int featureId);
int releaseFeatureEx(int featureId, int consumed, String scope);
void releaseFeatureEx2(Ticket ticket, int consumed);
FeatureInfo getFeatureInfo(int featureId);
int getFeatureInfo2(String featureName, String scope);
FeatureInfoEx getFeatureInfoEx2(String featureName, String scope);
TicketInfo getTicketInfo(Ticket ticket, TicketInfoType type);
byte[] signFeature(int featureId, byte[] data);
FeatureInfo getFeatureInfoByIndex(int index);
// 批量操作
BatchResult batchBegin(BatchMode mode);
BatchResult batchEnd();
}
DataItemStore
public interface DataItemStore {
void setDataItem(String name, byte[] value);
byte[] getDataItem(String name);
void removeDataItem(String name);
int getDataItemCount();
String getDataItemName(int index);
}
LicenseInfoQuery
public interface LicenseInfoQuery {
LicenseInfo getLicenseInfo();
String getSessionInfo(SessionType type);
String getInfo(InfoType type);
String getServerInfo(String url, String sn, String scope, ServerInfoType type);
}
CheckoutManager
public interface CheckoutManager {
void checkOut(String url, String scope, String featureList, int durationDays);
void checkOutSn(String url, int featureId, int durationDays);
void checkOutSnEx(String url, int featureId, String scope, int durationDays);
void checkOutFeatures(String url, int[] featureIds, int durationDays);
void checkIn(String url, int featureId);
void checkInEx(String url, int featureId, String scope);
String getBorrowRequest(String sn, int durationDays);
String getBorrowFeatureRequest(int durationDays, String scope);
void applyBorrowInfo(String borrowInfo);
}
LicenseUtility
public interface LicenseUtility {
void setAttr(int type, byte[] value);
void setCustomInfo(int infoId, byte[] data);
void setSessionState(int state);
String getProductPath();
int getLastError();
String getErrorMessage();
void testBitService(String url, String sn, int featureId);
}
3. 原生 Rust 层重构
3.1 目录结构
native/craft-core/src/
├── lib.rs # C ABI 入口,craft_* 函数声明
├── ffi/
│ ├── mod.rs
│ ├── bitanswer.rs # BitAnswer C API 的 Rust extern 声明
│ └── bridge.rs # craft_* → Bit_* 的桥接实现
├── session.rs # 会话管理,BIT_HANDLE 映射
├── activate.rs # 对接 Bit_Login / Bit_UpdateOnline
├── license.rs # 对接 Bit_GetSessionInfo / Bit_GetInfo
├── feature.rs # 对接 Bit_ReadFeature / Bit_WriteFeature / Bit_QueryFeature 等
├── data_item.rs # 对接 Bit_SetDataItem / Bit_GetDataItem 等
├── checkout.rs # 对接 Bit_CheckOutSn / Bit_CheckIn 等
├── heartbeat.rs # 对接 Bit_Heartbeat
├── security/ # 安全模块(保持不变)
│ ├── mod.rs
│ ├── anti_debug.rs
│ ├── dynamic_api.rs
│ ├── integrity.rs
│ ├── obfuscation.rs
│ └── string_encrypt.rs
└── error.rs # BIT_ERROR_CODES → LicenseError 映射
3.2 JNI 映射表(NativeBridge 扩展)
| Java 方法 | Rust craft_* | BitAnswer C API |
|---|---|---|
nativeInitialize(String) |
craft_initialize |
内部引导 |
nativeLogin(long, String, int) |
craft_login |
Bit_Login |
nativeLoginEx(long, String, int, String, int) |
craft_login_ex |
Bit_LoginEx |
nativeLoginByToken(long, String, String) |
craft_login_by_token |
Bit_LoginByToken |
nativeLoginByPassword(long, ...) |
craft_login_by_password |
Bit_LoginByPassword |
nativeLogout(long) |
craft_logout |
Bit_Logout |
nativeActivate(long, String) |
craft_activate |
Bit_UpdateOnline |
nativeGetRequestInfo(long, String, int) |
craft_get_request_info |
Bit_GetRequestInfo |
nativeGetUpdateInfo(long, String, String, String) |
craft_get_update_info |
Bit_GetUpdateInfo |
nativeApplyUpdateInfo(long, String) |
craft_apply_update_info |
Bit_ApplyUpdateInfo |
nativeReadFeature(long, int) |
craft_read_feature |
Bit_ReadFeature |
nativeWriteFeature(long, int, int) |
craft_write_feature |
Bit_WriteFeature |
nativeConvertFeature(long, int, int, int, int, int) |
craft_convert_feature |
Bit_ConvertFeature |
nativeEncryptFeature(long, int, byte[], int) |
craft_encrypt_feature |
Bit_EncryptFeature |
nativeDecryptFeature(long, int, byte[], int) |
craft_decrypt_feature |
Bit_DecryptFeature |
nativeQueryFeature(long, int) |
craft_query_feature |
Bit_QueryFeature |
nativeQueryFeatureEx(long, int, int, int, String) |
craft_query_feature_ex |
Bit_QueryFeatureEx |
nativeReleaseFeature(long, int) |
craft_release_feature |
Bit_ReleaseFeature |
nativeSignFeature(long, int, byte[], int) |
craft_sign_feature |
Bit_SignFeature |
nativeSetDataItem(long, String, byte[], int) |
craft_set_data_item |
Bit_SetDataItem |
nativeGetDataItem(long, String) |
craft_get_data_item |
Bit_GetDataItem |
nativeRemoveDataItem(long, String) |
craft_remove_data_item |
Bit_RemoveDataItem |
nativeGetDataItemNum(long) |
craft_get_data_item_num |
Bit_GetDataItemNum |
nativeGetDataItemName(long, int) |
craft_get_data_item_name |
Bit_GetDataItemName |
nativeCheckLicense(long) |
craft_check_license |
Bit_GetSessionInfo |
nativeGetLicenseInfo(long) |
craft_get_license_info |
Bit_GetInfo |
nativeGetSessionInfo(long, int) |
craft_get_session_info |
Bit_GetSessionInfo |
nativeGetServerInfo(long, String, String, String, int) |
craft_get_server_info |
Bit_GetServerInfo |
nativeGetFeatureInfo(long, int) |
craft_get_feature_info |
Bit_GetFeatureInfo |
nativeCheckOutSn(long, String, int, int) |
craft_check_out_sn |
Bit_CheckOutSn |
nativeCheckOutFeatures(long, String, int[], int, int) |
craft_check_out_features |
Bit_CheckOutFeatures |
nativeCheckIn(long, String, int) |
craft_check_in |
Bit_CheckIn |
nativeHeartbeat(long) |
craft_heartbeat |
Bit_Heartbeat |
nativeRevoke(long, String) |
craft_revoke |
Bit_Revoke |
nativeRemoveSn(long, String) |
craft_remove_sn |
Bit_RemoveSn |
nativeSetAttr(long, int, byte[]) |
craft_set_attr |
Bit_SetAttr |
nativeSetCustomInfo(long, int, byte[]) |
craft_set_custom_info |
Bit_SetCustomInfo |
nativeSetRootPath(long, String) |
craft_set_root_path |
Bit_SetRootPath |
nativeSetProxy(...) |
craft_set_proxy |
Bit_SetProxy |
nativeSetLocalServer(...) |
craft_set_local_server |
Bit_SetLocalServer |
nativeGetProductPath(long) |
craft_get_product_path |
Bit_GetProductPath |
nativeGetVersion() |
craft_get_version |
Bit_GetVersion |
nativeGetLastError(long) |
craft_get_last_error |
Bit_GetLastError |
nativeDestroy(long) |
craft_destroy |
资源释放 |
3.3 句柄管理
// session.rs
struct SessionState {
bit_handle: BIT_HANDLE, // Bit_Login 返回的句柄
config: AuthConfig, // 解析后的配置
application_data: Vec<u8>, // 产品识别码(来自 AuthConfig)
logged_in: bool,
}
static SESSIONS: Lazy<Mutex<HashMap<i64, SessionState>>> = ...;
4. 数据流
4.1 完整调用链(浮动作业激活)
Java: CraftLicense.initialize(configJson)
└─> Rust: craft_initialize(config_json)
├─ 解析 JSON → AuthConfig
├─ 安全加固检查(anti_debug, integrity)
├─ 创建 SessionState,分配 session_id
└─ 返回 session_id (i64)
Java: session.activate(ActivationRequest { sn: "SN-XXXX" })
└─> Rust: craft_activate(session_id, sn)
├─ 从 AuthConfig 获取 bitanswer.url, loginMode
├─ 调用 Bit_UpdateOnline(url, sn, &app_data)
└─ 返回 ActivationResult
Java: session.login(LoginRequest { sn: "SN-XXXX", mode: AUTO })
└─> Rust: craft_login(session_id, sn, mode)
├─ 调用 Bit_Login(url, sn, &app_data, &bit_handle, BIT_MODE_AUTO)
├─ 存储 bit_handle → SessionState
└─ 返回 LoginResult { handle }
Java: session.readFeature(FACE_FEATURE_ID)
└─> Rust: craft_read_feature(session_id, feature_id)
├─ 获取 bit_handle
├─ 调用 Bit_ReadFeature(bit_handle, feature_id, &value)
└─ 返回 value (i32)
Java: session.checkOutSn(url, FEATURE_ZERO, 30)
└─> Rust: craft_check_out_sn(session_id, url, feature_id, duration)
├─ 调用 Bit_CheckOutSn(url, feature_id, &app_data, duration)
└─ 返回 CraftResult
Java: session.release()
└─> Rust: craft_release(session_id)
├─ 调用 Bit_Logout(bit_handle)
└─ 返回 CraftResult
Java: session.close()
└─> Rust: craft_destroy(session_id)
├─ 如果未 logout,调用 Bit_Logout
├─ 移除 SessionState
└─ 释放内存
4.2 错误码映射
Rust 侧将 200+ 个 BIT_ERROR_CODES 分组映射为 LicenseError 枚举:
pub enum LicenseError {
Success,
NetworkError,
WrongHandle,
InvalidParameter,
ApplicationDataError,
LicenseExpired,
LicenseNotFound,
LicenseDisabled,
FeatureNotFound(i32),
FeatureExpired(i32),
FeatureTypeNotMatch(i32),
SnInvalid,
SnNotFound,
SnDisabled,
SnRevoked,
SnExpired,
CapacityExhausted,
ServerBusy,
ServerDown,
Revoked,
Timeout,
TokenError,
BorrowError,
Unknown(i32), // 兜底
}
Java 侧使用 sealed interface 提供类型安全的结果:
public sealed interface LicenseResult {
boolean isSuccess();
Optional<LicenseError> error();
String message();
}
5. 配置模型适配
AuthConfig 已有正确结构,重构后需将字段驱动到运行时:
| AuthConfig 字段 | 驱动行为 |
|---|---|
bitanswer.url |
Bit_Login / Bit_UpdateOnline 的 szURL |
bitanswer.loginMode |
Bit_Login 的 mode 参数 |
bitanswer.rootPath |
Bit_SetRootPath |
bitanswer.applicationData |
替代硬编码的 application_data[],使不同产品可携带不同识别码 |
features[].bitanswerFeatureId |
readFeature(featureId) / queryFeature(featureId) |
features[].bitanswerFeatureName |
queryFeatureEx2(featureName, ...) |
floating.projectId |
floating 场景校验(schema 已有) |
school.edgeDeviceId |
school 场景标识 |
6. 迁移路径
Phase 1 — 基础设施(不破坏现有接口)
- Rust:
ffi/bitanswer.rsFFI 声明 +bridge.rs桥接实现 - Rust: 实现
craft_activate,craft_check_license,craft_heartbeat的真实调用 - Java:
AuthProvider标记@Deprecated,内部委托给CraftLicense - Java: 新增
CraftLicense+LicenseSession+ 5 个能力接口(空实现) - 测试: 现有测试保持通过
Phase 2 — 核心 API 扩展
- Java: 实现
LicenseLifecycle(login, loginEx, revoke, removeSn) - Java: 实现
FeatureManagement(read, write, query, encrypt 等) - Rust: 实现对应的
craft_*函数 - 测试: 每个能力域独立集成测试
Phase 3 — 高级功能
- Java: 实现
DataItemStore(set/get/remove/enum) - Java: 实现
CheckoutManager(checkOut/In 系列) - Rust: 实现离线升级流程(GetRequestInfo → GetUpdateInfo → ApplyUpdateInfo)
- 文档: 更新
bitanswer-client-api-overview.md映射表
Phase 4 — 清理
- 移除
@Deprecated AuthProvider - 移除
.deprecated-cmake/下的旧适配器代码 - 全量回归测试
7. 兼容性
schemas/craftlabs-auth-config.schema.json— 不变- 现有
examples/config/*.json— 不变 AuthConfig/AuthConfigs— 不变AuthProvider— Phase 1-3 保持可用(@Deprecated),Phase 4 移除NativeBridge— 现有 9 个方法保留,新增 30+ 方法craft-coreC ABI — 现有 9 个函数签名不变,新增 30+ 函数
8. 风险与缓解
| 风险 | 缓解 |
|---|---|
| Rust FFI 调用 BitAnswer .so/.dll 的链接问题 | Phase 1 先用 libloading 动态加载 BitAnswer 库,验证 ABI 兼容性 |
| 200+ 错误码映射不完整 | 只映射文档中明确列出的错误码,其余走 Unknown(code) |
| 多线程安全(BIT_HANDLE 是线程局部的) | LicenseSession 文档注明非线程安全,建议调用方池化或加锁 |
| native 库缺失时测试无法运行 | 单元测试 mock native 层,集成测试用 @EnabledIfNativeLibraryPresent |
附录 A:审计发现记录
审计过程中发现的具体代码问题:
- Rust
activate.rs:core_activate— 返回硬编码ok_result,未调用任何 BitAnswer API - Rust
license.rs:check_license— 返回硬编码ok_result - Rust
license.rs:get_license_info— 返回固定数据(is_licensed=1,expiration_date="2099-12-31",feature_count=0) - Rust
license.rs:has_feature— 无条件返回true - Rust
heartbeat.rs:do_heartbeat— 返回硬编码ok_result - Java
BitAnswerProvider.initialize— 配置 JSON 未被传递给 native 层做运行时行为驱动 NativeBridge— 只有 9 个 JNI 方法,BitAnswer 有 50+ 函数.deprecated-cmake/bitanswer_adapter.cpp—bitanswer_adapter_register()是空函数
附录 B:BitAnswer C API 完整清单
见 examples/vcsample/bitanswer.h(1211 行),包含 50+ 个 Bit_* 函数声明和 200+ 个错误码枚举。