☰
Current Page
Main Menu
Home
Home
Editing
平台和app授权设计与实现
Edit
Preview
h1
h2
h3
default
Set your preferred keybinding
default
vim
emacs
markdown
Set this page's format to
AsciiDoc
Creole
Markdown
MediaWiki
Org-mode
Plain Text
RDoc
Textile
Rendering unavailable for
BibTeX
Pod
reStructuredText
Help 1
Help 1
Help 1
Help 2
Help 3
Help 4
Help 5
Help 6
Help 7
Help 8
Autosaved text is available. Click the button to restore it.
Restore Text
### 1,需求分析 在实际的软件部署流程中,为了防止一套售出的软件被随意在多个平台进行部署,那么就需要对软件系统进行授权,只有在获取到授权后才能使用,常用的方法无非两种, 其一是软件认证, 其二是硬件绑定。 软件认证,顾名思义就是在软件层面的一种认证手段,常用的方法就是注册账号设置密码。 只要账号密码正确,在任何设备上都可使用。 硬件绑定,就是将软件和硬件设备进行捆绑,也就是说一旦完成捆绑后,该软件就只能在该硬件设备上使用了。 两种授权方法各有优劣,因应用场景的不同而选择不同的方案,在此就不多做讨论了, 本文主要探讨的是硬件绑定的方法,以在PC机的软件授权为背景进行授权码的设计。 ### 2,方案选型 方案一:硬件绑定。考虑到虚拟机部署,无法确定具体的硬件信息,但是通过挂在宿主机的/sys/class/net/eth0/address文件,则可以获取宿主机的mac地址。 方案二:结合方案一,同时通过限制部署节点的个数、cpu mem使用情况来防止大规模的部署,在可控范围内起到一定的限制作用。 授权机制的过程和原理: - 生成密钥对,包含私钥和公钥,私钥签名,公钥验签。 - 授权者保留私钥,使用私钥对授权信息诸如使用截止日期、mac地址、限定的资源和appID等内容生成 license签名证书。 - 公钥给使用者,放在代码中使用,用于验证 license 签名证书是否符合使用条件,比如部署节点个数是否在限定范围内。 - 各个部署节点分别定时向鉴权服务注册自己的信息,包括设备id,cpu mem等资源情况。 - 如果设备下线或者不适用,则请求反注册接口,释放自己的资源。如果节点长时间(一天)没有上报信息则自动过期。 - 授权服务统计上报节点的各资源信息并统计,如果已经超过了license规定的资源限定值则返回授权失败。 ### 3,技术实现 ### 编译命令行工具 编译工具需要安装[Go1.19](https://go.dev/dl/)和`make`命令,设置[Go模块代理](https://goproxy.cn/) ```shell # 切换到本项目根目录,执行以下命令编译工具 make build_tool make build_api # 编译生成 api 服务 # 默认命令行工具将会输出build目录,切换到build目录,执行以下命令 cd build autool #显示全部命令 autool version #显示工具版本号 autool help version #显示version命令帮助信息 # 如果是在linux环境,可能需要执行以下命令 chmod +x autool ./autool #显示全部命令 ``` ### 创建授权证书&编译程序库 创建授权证书基本步骤: - 创建密钥文件,或者使用已有密钥文件 - 修改命令行工具配置文件`tool.toml`,设置授权信息 ``` [license] User = '1'#授权用户 ExpiredAt = '20240101' # 授权到期日期,格式:YYYYMMDD EngineVersion = 'v1.0.0' # 引擎版本 FingerPrint = 'xxx' # 指纹 MacAddress = '00:ff:42:c3:58:9a' # 网卡Mac地址,多个逗号分隔 PhysicalID = '178BFBFF00A50F00' # cpu序列号 # 资源限定 Cpu = 1024 # cpu核数 Mem = 1024 # 内存k Node = 10 # 节点个数 CompanyName = "test" # 企业名称 ContractID = "fdfdj12345jjfjd" # 合同id LesseeID = 123 # 租户id AppID = [1,2,3,4] # 授权的app id,多个以逗号隔开 ``` - 创建&加密授权证书 - 编译程序库,嵌入加密后证书 ```shell # 项目包含1份示例配置文件,见`conf/tool.toml` # 以下假设autool已经存在于bulid目录下 # 打开命令行窗口 cd build mkdir -o conf cp ../conf/tool.toml ./conf/ # 创建密钥文件,文件默认输出到: conf/key.pem, conf/key_pub.pem autool newkey # 修改tool.toml,根据实际情况设置授权证书信息,见"[license]" # 如果设置mac地址,则调用接口时会校验服务器mac地址是否已授权 # 可执行以下命令查看本机mac地址 autool mac # 创建加密授权证书,文件默认输出到:conf/license autool newlic # 编译程序库,加密证书和对应的公钥文件会嵌入程序库里 # 如果需要使用已有证书和公钥,可修改tool.toml->PubKeyFile/LicenseFile # windows环境,库文件输出到:parser.dll # linux环境,库文件输出到:libparser.so # 注:Go目前不支持通过设置GOOS来编译不同环境下的动态库文件 autool newlib # 启动api服务 chmod +x api ./api ``` ### api 接口 ##### aes加密方案 所有请求数据和返回数据均通过aes加密,32位秘钥是:Y8uCrLL8SavXyiUzpnU+Lmn4mODprYLo 所以,发送和接收到的body,都是经过加密后的数据,比如: ``` 实际请求: { "device_id": "3", "cpu": 4, "mem": 1024, "engine_version": "v1.0.0" } 加密后的请求: ��2.�&%Y���g�|�Q��-V�ݧa��%yIO;��6��ֵYb1}���5���ޭ��Pޕ<Q8�ڍ���j��E�ܯ��缰BsbV`�0�F0w 同理,接收到的body也是加密的 实际返回: { "code": 0, "err": "", "data": "" } 加密后的返回: (w�`�'�gDk� : 4$C������n ]�����[rr���fl�ff��sk`J ``` - 注册 ``` POST localhost:8080/api/v1/register 请求body: { "device_id": "3", "cpu": 4, "mem": 1024, "engine_version": "v1.0.0" } 返回: { "code": 0, "err": "", "data": "" } ``` - 反注册 ``` POST localhost:8080/api/v1/unregister 请求body: { "device_id": "2" } 返回: { "code": 0, "err": "", "data": "" } ``` - 鉴权 ``` POST localhost:8080/api/v1/auth 请求: { "app_id": ["1","2","3"] } 返回成功: { "code": 0, "err": "", "data": { "user": "1", "engine_version": "v1.0.0", "expired_at": "20240101", "finger_print": "xxx", "mac_address": "", "physical_id": "", "cpu": 1024, "mem": 1024, "node": 10, "app_id": [ "1", "2", "3" ] } } 授权失败返回: { "code": 121, "err": "unauthorized failed", "data": null } ``` ### web前端接口 参考下图:  - 获取服务信息 ``` POST localhost:8080/api/v1/service_info 请求: { "lease_id": "123456", "app_id": ["1","2", "oppmApp"], "cpu": 1024, "mem": 1024, "node": 100, "engine_version": "v1.0.0", "expired_at": "20240101" } 返回成功: { "code": 0, "err": "", "data": "HWqwL0TBDyULAiZPv0u5zRst6OHfnv8AC7gDoxeXA97ceSh2OeG80hX0ZaxoAHoR7I2M/WlsojCq2KK/ao4UyRm711YVM+jS+X+b67dBYE5eNXHrMpzWpPryd3fh09f0w7ghnp2ZJ++THIBTio/hJp3Nk2gwlLTnM4jLkb3ZD8Yb/+kOJrirDN4QKzGguejK+95aiCPbH7VzW9sVfJQsijBWFyzDto2Qp2Rr7o0uESFMC4HWE1yrNQzAoeQUy7Qr4yBsF04UGZWPrjGwGGChIms6zosFOKAgvzKMwUX94TfCDfP5RsdG4EVIe7cxkk86j175hlLn162kglZGRI+PsA==" } 授权失败返回: { "code": 121, "err": "", "data": null } ``` - 提交授权许可 ``` POST localhost:8080/api/v1/submit 请求: { "license": "xxxxxxx", } 返回成功: { "code": 0, "err": "", "data": null } 授权失败返回: { "code": 121, "err": "submit err", "data": null } ``` ### 计划 - 3月27-3月29 完成整个授权码功能的后端接口开发并自测 - 3月30-3月31 完成联调
Uploading file...
Sidebar
[[_TOC_]]
Edit message:
Cancel