golang简单高效的许可证管理插件库lk的使用
Golang简单高效的许可证管理插件库lk的使用
lk是一个简单高效的Golang许可证管理库,它可以生成包含任意数据(如用户邮箱、截止日期等)的许可证文件,并支持验证这些许可证。
工作原理
- 生成一个私钥(并保持安全)
- 将你想要提供的数据(截止日期、用户邮箱等)转换为字节数组(使用json或gob等)
- 库获取数据并创建一个加密签名的哈希,附加到数据中
- 将结果转换为Base64/Base32/Hex字符串并发送给最终用户:这就是许可证
- 当用户启动程序时,加载许可证并使用公钥验证签名
- 验证许可证密钥中的数据(如截止日期)
完整示例
1. 生成新许可证
// 首先,你需要一个由`lkgen gen`生成的base32编码的私钥
// 注意你可能更愿意从文件中读取它,并且它应该保持机密(即不要随应用程序分发!)
const privateKeyBase32 = "FD7YCAYBAEFXA22DN5XHIYLJNZSXEAP7QIAACAQBANIHKYQBBIAACAKEAH7YIAAAAAFP7AYFAEBP7BQAAAAP7GP7QIAWCBCRKQVWKPT7UJDNP4LB5TXEQMO7EYEGDCE42KVBDNEGRIYIIJFBIWIVB6T6ZTKLSYSGK54DZ5VX6M5SJHBYZU2JXUFXJI25L2JJKJW4RL7UL2XBDT4GKYZ5IS6IWBCN7CWTMVBCBHJMH3RHZ5BVGVAY66MQAEYQEPSS2ANTYZIWXWSGIUJW3MDOO335JK3D4N3IV4L5UTAQMLS5YC7QASCAAUOHTZ5ZCCCYIBNCWBELBM===="
// 解组私钥
privateKey, err := lk.PrivateKeyFromB32String(privateKeyBase32)
if err != nil {
log.Fatal(err)
}
// 定义许可证中需要的数据
// 这里我们使用一个被编组成json的结构体,但最终你只需要一个[]byte
doc := struct {
Email string `json:"email"`
End time.Time `json:"end"`
}{
"user@example.com",
time.Now().Add(time.Hour * 24 * 365), // 1年
}
// 将文档编组为[]bytes(这是我们的许可证将包含的数据)
docBytes, err := json.Marshal(doc)
if err != nil {
log.Fatal(err)
}
// 用私钥和文档生成你的许可证
license, err := lk.NewLicense(privateKey, docBytes)
if err != nil {
log.Fatal(err)
}
// 许可证的b32表示,这是你给客户的东西
licenseB32, err := license.ToB32String()
if err != nil {
log.Fatal(err)
}
fmt.Println(licenseB32)
2. 验证许可证
// 一个之前生成的b32编码的许可证。在实际应用中你应该从文件中读取它...
const licenseB32 = "FT7YOAYBAEDUY2LDMVXHGZIB76EAAAIDAECEIYLUMEAQUAABAFJAD74EAAAQCUYB76CAAAAABL7YGBIBAL7YMAAAAD73H74IAFEHWITFNVQWS3BCHIRHIZLTORAGK6DBNVYGYZJOMNXW2IRMEJSW4ZBCHIRDEMBRHAWTCMBNGI3FIMJSHIYTSORTGMXDOMBZG43TIMJYHAVTAMR2GAYCE7IBGEBAPXB37ROJCUOYBVG4LAL3MSNKJKPGIKNT564PYK5X542NH62V7TAUEYHGLEOPZHRBAPH7M4SC55OHAEYQEXMKGG3JPO6BSHTDF3T5H6T42VUD7YAJ3TY5AP5MDE5QW4ZYWMSAPEK24HZOUXQ3LJ5YY34XYPVXBUAA===="
// 公钥b32编码,使用`lkgen pub my_private_key_file`从私钥生成
// 它应该硬编码在你的应用程序中
const publicKeyBase32 = "ARIVIK3FHZ72ERWX6FQ6Z3SIGHPSMCDBRCONFKQRWSDIUMEEESQULEKQ7J7MZVFZMJDFO6B46237GOZETQ4M2NE32C3UUNOV5EUVE3OIV72F5LQRZ6DFMM6UJPELARG7RLJWKQRATUWD5YT46Q2TKQMPPGIA===="
// 解组公钥
publicKey, err := lk.PublicKeyFromB32String(publicKeyBase32)
if err != nil {
log.Fatal(err)
}
// 解组客户许可证
license, err := lk.LicenseFromB32String(licenseB32)
if err != nil {
log.Fatal(err)
}
// 验证许可证签名
if ok, err := license.Verify(publicKey); err != nil {
log.Fatal(err)
} else if !ok {
log.Fatal("Invalid license signature")
}
result := struct {
Email string `json:"email"`
End time.Time `json:"end"`
}{}
// 解组文档
if err := json.Unmarshal(license.Data, &result); err != nil {
log.Fatal(err)
}
// 现在你只需要检查截止日期是否在当前时间之后,然后就可以继续了!
if result.End.Before(time.Now()) {
log.Fatalf("License expired on: %s", result.End.Format("2006-01-02"))
} else {
fmt.Printf(`Licensed to %s until %s`, result.Email, result.End.Format("2006-01-02"))
}
3. 完整示例
// 创建一个新的私钥:
privateKey, err := lk.NewPrivateKey()
if err != nil {
log.Fatal(err)
}
// 创建一个许可证文档:
doc := MyLicence{
"test@example.com",
time.Now().Add(time.Hour * 24 * 365), // 1年
}
// 将文档编组为json字节:
docBytes, err := json.Marshal(doc)
if err != nil {
log.Fatal(err)
}
// 用私钥和文档生成你的许可证:
license, err := lk.NewLicense(privateKey, docBytes)
if err != nil {
log.Fatal(err)
}
// 将新许可证编码为b64,这是你给客户的东西
str64, err := license.ToB64String()
if err != nil {
log.Fatal(err)
}
fmt.Println(str64)
// 获取公钥。公钥应该硬编码在你的应用程序中以检查许可证
// 不要分发私钥!
publicKey := privateKey.GetPublicKey()
// 验证许可证:
if ok, err := license.Verify(publicKey); err != nil {
log.Fatal(err)
} else if !ok {
log.Fatal("Invalid license signature")
}
// 解组文档并检查截止日期:
res := MyLicence{}
if err := json.Unmarshal(license.Data, &res); err != nil {
log.Fatal(err)
} else if res.End.Before(time.Now()) {
log.Fatalf("License expired on: %s", res.End.String())
} else {
fmt.Printf(`Licensed to %s until %s \n`, res.Email, res.End.Format("2006-01-02"))
}
这个库使用椭圆曲线数字签名算法(使用elliptic.P384)来签名许可证文件,并且许可证可以以易于分发的格式(如base32编码字符串)进行编组。
更多关于golang简单高效的许可证管理插件库lk的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang简单高效的许可证管理插件库lk的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 许可证管理插件库 lk 使用指南
lk 是一个简单高效的 Golang 许可证管理库,可以帮助开发者轻松实现软件许可证的生成、验证和管理功能。下面我将详细介绍如何使用这个库。
安装
首先使用 go get 安装 lk 库:
go get github.com/yourusername/lk
基本用法
1. 创建许可证
package main
import (
"fmt"
"github.com/yourusername/lk"
)
func main() {
// 创建新的许可证
license := lk.NewLicense()
// 设置许可证属性
license.Set("name", "John Doe")
license.Set("email", "john@example.com")
license.Set("expiry", "2023-12-31")
license.Set("features", []string{"feature1", "feature2"})
// 生成许可证密钥
key, err := license.Generate("your-secret-key")
if err != nil {
fmt.Println("生成许可证失败:", err)
return
}
fmt.Println("生成的许可证密钥:", key)
}
2. 验证许可证
package main
import (
"fmt"
"github.com/yourusername/lk"
)
func main() {
// 假设这是从用户获取的许可证密钥
licenseKey := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
// 验证许可证
license, err := lk.Validate(licenseKey, "your-secret-key")
if err != nil {
fmt.Println("许可证验证失败:", err)
return
}
// 获取许可证信息
name, _ := license.Get("name")
email, _ := license.Get("email")
expiry, _ := license.Get("expiry")
fmt.Printf("许可证信息:\n名称: %s\n邮箱: %s\n过期时间: %s\n", name, email, expiry)
}
高级功能
1. 自定义验证规则
package main
import (
"fmt"
"time"
"github.com/yourusername/lk"
)
func main() {
licenseKey := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
// 自定义验证函数
customValidator := func(license *lk.License) error {
// 检查过期时间
expiry, err := license.Get("expiry")
if err != nil {
return fmt.Errorf("无效的许可证: 缺少过期时间")
}
expiryTime, err := time.Parse("2006-01-02", expiry.(string))
if err != nil {
return fmt.Errorf("无效的过期时间格式")
}
if time.Now().After(expiryTime) {
return fmt.Errorf("许可证已过期")
}
// 检查必要特性
features, err := license.Get("features")
if err != nil {
return fmt.Errorf("无效的许可证: 缺少特性列表")
}
requiredFeatures := []string{"feature1", "feature2"}
for _, req := range requiredFeatures {
found := false
for _, f := range features.([]string) {
if f == req {
found = true
break
}
}
if !found {
return fmt.Errorf("缺少必要特性: %s", req)
}
}
return nil
}
// 带自定义验证的许可证检查
license, err := lk.ValidateWith(licenseKey, "your-secret-key", customValidator)
if err != nil {
fmt.Println("许可证验证失败:", err)
return
}
fmt.Println("许可证验证通过:", license)
}
2. 许可证续期
package main
import (
"fmt"
"time"
"github.com/yourusername/lk"
)
func renewLicense(oldKey string, newExpiry time.Time) (string, error) {
// 验证旧许可证
license, err := lk.Validate(oldKey, "your-secret-key")
if err != nil {
return "", fmt.Errorf("无法续期无效的许可证: %v", err)
}
// 更新过期时间
license.Set("expiry", newExpiry.Format("2006-01-02"))
// 生成新许可证
newKey, err := license.Generate("your-secret-key")
if err != nil {
return "", fmt.Errorf("生成新许可证失败: %v", err)
}
return newKey, nil
}
func main() {
oldKey := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
newExpiry := time.Now().AddDate(1, 0, 0) // 延长一年
newKey, err := renewLicense(oldKey, newExpiry)
if err != nil {
fmt.Println("续期失败:", err)
return
}
fmt.Println("新的许可证密钥:", newKey)
}
最佳实践
-
密钥安全:确保你的密钥安全,不要硬编码在代码中,可以使用环境变量或配置文件。
-
定期检查:在应用程序中定期检查许可证有效性,而不仅仅在启动时。
-
特性控制:使用许可证中的特性列表来控制应用程序的不同功能模块。
-
错误处理:为用户提供友好的错误信息,同时记录详细的验证错误日志。
-
离线验证:考虑实现离线验证机制,允许用户在无网络连接时使用。
lk 库提供了简单而强大的许可证管理功能,通过合理使用可以有效地保护你的软件产品。根据你的具体需求,可以进一步扩展和定制验证逻辑。