授权激活
授权激活指的是从服务器获取license文件后保存在本地,供其它程序使用。激活后的license文件默认位置如下:
- Linux:“{当前用户}/BitAnswer”
- Windows:“{系统盘}/ProgramData/BitAnswer”
该目录也可以通过Bit_SetRootPath来自定义。
授权激活支持在线和离线两种方式。
在线激活
- 使用SN激活
调用Bit_UpdateOnline,传入SN激活。
示例:
// 激活SN(YUFTB2AY4AAACVB6)
BIT_STATUS status = Bit_UpdateOnline(NULL, “YUFTB2AY4AAACVB6”, application_data);
If (status == BIT_SUCCESS) {
// 激活成功
printf(“激活成功\n”);
} else {
// 激活失败,错误码是status
printf(“激活失败,错误码%d\n”,status);
}
- 使用BIT-ID激活
当SN与BIT-ID已经在服务端绑定过,则可以在客户端使用BIT-ID直接激活。
使用Bit_UpdateOnline激活,第二个参数传入#0,#1,#....,代表激活第一个BIT-ID,激活第二个BIT-ID,激活第N个BIT-ID。
示例:
// 激活插入的第一个BIT-ID
BIT_STATUS status = Bit_UpdateOnline(NULL, “#0”, application_data);
If (status == BIT_SUCCESS) {
// 激活成功
printf(“激活成功\n”);
} else {
// 激活失败,错误码是status
printf(“激活失败,错误码%d\n”,status);
}
// 激活插入的第二个BIT-ID
Bit_UpdateOnline(NULL, “#1”, application_data);
离线激活
-
标准流程
-
在需要激活的设备上调用Bit_GetRequestInfo接口获取请求串。
-
将请求串拷贝到可以联网的设备,上传到比特授权云平台来获取license串。
-
将license串拷贝到需要激活的设备上调用Bit_ApplyUpdateInfo接口进行激活。
-

示例:
BIT_STATUS status = BIT_SUCCESS;
BIT_CHAR buff[1024] = { 0 };
BIT_UINT32 lenBuff = sizeof(buff);
// 获取请求串
status = Bit_GetRequestInfo(“<SN>”, application_data, BINDING_LOCAL, buff, &lenBuff);
if (status == BIT_SUCCESS) {
// 请求串获取成功,保存在buff,长度时lenBuff
} else {
// 获取请求串错误
}
// 拷贝到可以联网的设备,获取license串,最后拷贝会待激活设备
BIT_CHAR *pLicense = “<拷贝的license串>”;
status = Bit_ApplyUpdateInfo(application_data, pLicense, buff, &lenBuff);
if (status == BIT_SUCCESS) {
// 激活成功
} else {
// 激活失败
}
- 使用设备码激活
对于标准的激活流程需要在产生请求串时输入SN,请求串产生后还需要将其拷贝出来。但是在某些涉密单位不允许向外拷贝文件,而请求串又太长,手动输入太麻烦,因此比特授权云平台支持使用设备码进行激活。
设备码的激活流程和标准的离线激活流程一样,只是在获取请求串时,获取的是易手输的设备码。
示例:
BIT_STATUS status = BIT_SUCCESS;
BIT_CHAR buff[1024] = { 0 };
BIT_UINT32 lenBuff = sizeof(buff);
// 获取请求串
status = Bit_GetRequestInfo(NULL, application_data, REQ_TYPE_MID, buff, &lenBuff);
if (status == BIT_SUCCESS) {
// 设备码获取成功,保存在buff,长度时lenBuff
} else {
// 获取设备码错误
}
// 获取的设备类似:BRW118347F668638A02D5D069F64DA0199D200A531AD13C80C2
- 使用单项升级串
当设备已经激活,后续如果需要对授权进行升级,就可以不需要产生请求串,而直接通过比特授权云平台下发license串。
使用license串时调用Bit_ApplyUpdateInfo。
- 比较
项 | 标准离线激活 | 设备码激活 |
---|---|---|
是否需要输入SN? | 是 | |
请求串的长度 | 300个字节以上 | 100字符以内(容易手动输入、拷贝) |
是否支持终端标识?(自定义指纹) | 支持 | |
支持增量更新?(只升级更新的部分) | 支持 |
内存授权
内存授权不需要激活就可以直接使用。
- 获取license串
使用离线的方式获取到license串,获取到的串如下图:
<bitLicense>
<version>3</version>
<sn>FPIW6BX5********</sn>
<code>Uk4GSI3jwrh…………………nLc=</code>
</bitLicense>
-
读取license串里的code部分,组合成“lic:// Uk4GSI3jwrh……”
-
调用Bit_Login时传入
BIT_HANDLE handle = NULL;
BIT_STATUS status = Bit_Login(
“lic:// Uk4GSI3jwrh……”,
NULL,
application_data,
&handle,
BIT_MODE_LOCAL);
If (status == BIT_SUCCESS) {
// 内存license加载成功
}
授权检查
开发商需要在软件里设置授权检查点,一般来讲在软件开始运行时调用Bit_Login来检查是否有可用的授权,在运行到某个功能点时调用Bit_QueryFeature来检查授权里是否包某个特征项。
- 检查license
使用Bit_Login来检查license是否有效。
示例:
BIT_STATUS status = BIT_SUCCESS;
BIT_HANDLE handle = NULL;
status = Bit_Login(NULL, NULL, application_data, &handle, BIT_MODE_AUTO);
if (status == BIT_SUCCESS) {
// 获取license成功
// 执行业务逻辑
} else {
// 获取license失败
}
- 检查特征项
使用Bit_QueryFeature来检查特征项是否有效。
示例:
BIT_STATUS status = BIT_SUCCESS;
BIT_HANDLE handle = NULL;
BIT_UINT32 capacity = 0;
status = Bit_Login(NULL, NULL, application_data, &handle, BIT_MODE_AUTO);
if (status != BIT_SUCCESS) {
// 获取license失败
return;
}
status = Bit_QueryFeature(handle, <特征项Id>, &capacity);
if (status == BIT_SUCCESS) {
// 特征项有效
// 执行业务逻辑
} else {
// 获取特征项失败
}
- 程序运行过程中的检查
当程序运行过程中授权到期时,开发商软件可以通过如下方式检测到:
集团授权:设置心跳回调函数,在回调函数里处理到期事件(参考心跳认证)。
单机授权:定期调用Bit_GetSessionInfo来检查授权是否到期。
授权配置
客户端支持通过配置文件或者环境变量来控制授权行为,例如:配置客户端的授权服务器地址;配置授权模式等。
配置文件
配置文件目前仅支持配置授权服务地址。
配置文件存在两个地方,一个是授权目录,一个是软件当前目录,如果都存在则优先级是:授权目录 > 软件当前目录。
授权目录,默认地址:
- Linux:“{当前用户}/BitAnswer/{product-code}/bit_config.xml”
- Windows:“{系统盘}/ProgramData/BitAnswer/{product-code}/bit_config.xml”
其中product-code是产品路径。
内容:
<?xml version="1.0" encoding="UTF-8"?>
<BitConfig>
<Server Host="<集团服务IP>" Type="bit" Port="<集团服务端口>" Timeout="8" />
</BitConfig>
环境变量
名称 | 值 | 说明 |
---|---|---|
BITANSWER_LICENSE | 格式1:bit://ip1:port,bit://ip2:port 格式2:port@ip1,port@ip2, port@ip3 格式3:port@ip1:port@ip2,:port@ip3 |
指定license的地址,目前最多支持设置6个ip地址 |
BITANSWER_CONNECT_TIMEOUT | 数字(最小1秒,最大32秒,默认3秒) | 设置网络超时时间,单位秒 |
BITANSWER_CONNECT_RETRY_COUNT | 数字(最小0次,最大10次,默认3次) | 设置网络重试次数 |
BITANSWER_MODE | wait | nowait | 设置Query的模式。 wait:排队等待。 nowait:立即返回 |
BITANSWER_WAIT_TIMEOUT | 数字(最小16s,最大1296000s(15天),默认0,代表永久等待) | 设置wait模式的等待时间 |
自定义环境变量前缀,使用Bit_SetCustomInfo可以自定义前缀。
示例:
CHAR *pPre = “BIT”;
Bit_SetCustomInfo(CUSTOM_VENDOR_CODE, pPre, strlen(pPre));
// 设置成功之后,就可以使用类似“BIT_MODE, BIT_LICENSE, BIT_CONNECT_TIMEOUT…”这样的名称设置环境变量
如果环境变量和配置文件同时存在,则优先级是:环境变量 > 配置文件。
集团授权配置客户端IP轮询
对于集团授权,客户端需要配置IP才可以访问,当客户端配置了多个IP时,客户端在检查授权时会挨个匹配,直到找到可用的license。
以下场景,可以考虑使用客户端轮询:
- 增加网络的可靠性。当某一个服务器的网络出现问题时,不影响客户端的运行。
- 根据地理位置做负载均衡。例如:开发商在北京激活5个license,在上海激活5个license,对于北京的用户可以配置“北京IP,上海IP”,对于上海的用户可以配置“上海IP,北京IP”。
IP配置
当客户端请求集团授权失效后,就会尝试连接下一个IP,其顺序按照配置文件的顺序从上到下,如果是环境变量,则从前到后。
- 配置文件顺序示例(匹配顺序ipA-ipB-ipC):
// 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<BitConfig>
<Server Host="ipA" Type="bit" Port="8273"/>
<Server Host="ipB" Type="bit" Port="8273" />
<Server Host="ipC" Type="bit" Port="8273" />
</BitConfig>
- 环境变量顺序示例(匹配顺序ipA-ipB-ipC):
BITANSWER_URL=port@ipA,port@ipB,port@ipC
服务器选择
客户端选择服务器只会发生在首次连接时,一旦授权成功,后续的操作就只针对当前服务。
一般来讲,用户的调用流程如下:

对于13.4.0及下版本的客户端库,调用Bit_Login时会连接集团服务,只会检查SN是否有效(不检查特征项)。
示例说明:
- 有A(包含特征项A),B(包含特征项B),C(包含特征项A,B,C)三台服务器。
- 客户端调用Bit_Login连接到服务A。
- 客户端调用Bit_QueryFeatureEx2(handle, B, …),请求B特征项,由于handle已经连接到了A,所以在A服务器上查找B,没有找到B,直接报错“特征项不存在”。
对于13.4.0以上版本的客户端库,支持了一种新的登录模式LOGIN_MODE_CREATE_HANDLE_ONLY,在该模式下,Bit_Login只创建本地的handle(不连接集团服务),使用该handle调用Query相关接口才会连接服务,此时,服务会同时检查SN的有效性以及特征项的有效性。
注意:该功能需要服务端升级到13.4.0以上版本才可以支持,对于13.4.0及以下版本的服务调用会报错“服务版本太老”。
示例:
- 有A(包含特征项A),B(包含特征项B),C(包含特征项A,B,C)三台服务器。
- 客户端调用Bit_Login(LOGIN_MODE_CREATE_HANDLE_ONLY, …),创建本地handle。
- 客户端调用Bit_QueryFeatureEx2(handle, B, …),请求B特征项,由于handle还没有指定服务器,所以开始轮询查找包含特征项B的服务器,找到后将handle与服务器的session关联。
- 客户端如果继续使用上面的handle,去Query(handle, C, …),此时就只会在B服务器上查找C特征项,如果没有就会报“特征项不存在”的错误。
开发商如何实现不同特征项连接不同的服务器?
每一个特征项用一个不同的handle。
集团授权配置心跳认证
当客户端连接到集团授权,就会启动一个后台线程来维护客户端与集团服务的心跳连接,当超过10分钟(默认值)客户端没有发送过心跳,集团服务就会释放占用的用户数。
客户端的心跳周期是:1/2个timeout时间(默认5分钟),如果本次心跳失败,则下一次的心跳周期是10秒。
心跳模式
- 自动心跳
Bit_Login到集团授权时,会启动自动心跳。
- 手动心跳
手动心跳前需要调用Bit_SetAttr关闭自动心跳。
关闭后调用Bit_Heartbeat来触发心跳。
示例:
BIT_STATUS status = BIT_SUCCESS;
BIT_UINT32 enableHb = 0;
status = Bit_SetAttr(NULL, ATTR_HB_AUTO_ENABLE, &enableHb);
if (status != BIT_SUCCESS) {
// 禁用自动心跳失败
return;
}
BIT_UINT32 reconnectsNum = 0;
// handle 来自于Bit_Login
status = Bit_Heartbeat(handle, &reconnectsNum);
if (status != BIT_SUCCESS) {
// 心跳失败
return;
}
心跳回调
客户端连接到集团授权后,当集团授权失效(授权到期,服务器关闭,…),开发商软件需要处理该消息(例如:停止当前作业)。
心跳状态与license状态相关,当心跳重试次数达到上限或者断开时间超过timeout,则认为授权失效,心跳断开,反之心跳就会自动重试。
开发商软件通过向客户端库注册心跳回调函数来捕获心跳状态:
- 注册心跳失败回调
客户端心跳连接失败时,每重试一次就会触发一次,通过Bit_SetAttr来注册心跳失败回调。
示例:
/*
handle:心跳失败对应的handle
status:心跳失败的状态码
pData:保留
*/
void HbRetryFailedCallback(BIT_HANDLE handle, BIT_STATUS status, void *pData) {
}
Bit_SetAttr(handle, ATTR_HB_RETRY_FAILED_CALLBACK, HbRetryFailedCallback);
- 注册心跳停止回调
客户端心跳连接断开后,会触发一次,使用Bit_SetAttr注册心跳停止回调。
示例:
/*
handle:心跳失败对应的handle
pData:保留
*/
void HbStopedCallback(BIT_HANDLE handle, void *pData) {
}
Bit_SetAttr(handle, ATTR_HB_STOPED_CALLBACK, HbStopedCallback);
心跳配置
参考Bit_SetAttr说明。
Session重建
客户端登录集团服务后会在服务端创建Session,该Session保存了客户端与集团服务的会话信息。
当服务端Session丢失后(服务重启),客户端的心跳会检测到并重建Session,如果Session重建成功则恢复占用的授权点数,如果重建失败,则通过回调函数通知开发商软件。
当客户端Session丢失后(客户端强杀,崩溃),服务端会保持之前占用的点数,超过timeout时间后,集团服务就会自动释放。如果需要立即释放,需要在调用Bit_Login时设置长连接属性。
单机授权智能认证
对于单机授权,如果设置了智能认证选项,客户端每天就会连一次服务器进行认证。
Bit_Login成功后,会创建一个线程用来智能认证,如果认证成功,下一次的认证就是24小时后,如果认证失败,1分钟之后会再次尝试。
对于设置了强制认证属性的授权码,此机制可以保证其便利的用户体验。
授权借出
授权借出指的是从授权服务器借出一定的点数给客户端离线使用。
场景:
当用户无法连接到集团授权时才需要借出使用,例如:公司购买了集团授权供员工使用,但是有的员工需要在家里加班或者出差使用,借出后占用一个授权点数,借出到期后授权点数自动返还(可以调用Bit_CheckIn主动归还)。
调用Bit_CheckOutSn进行在线借出。
注意:只有集团授权和帐号授权勾选了借出属性后才支持借出。
集团授权活跃检测
集团授权的点数对于用户来讲非常的昂贵,用户希望在客户端空闲时能自动释放授权供其他人使用,此时就需要用到此功能。
开发商的软件需要调用Bit_SetSessionState向集团服务报告当前客户端的状态,该状态通过心跳传递给集团服务。
调用示例见Bit_SetSessionState。