亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

Spring Boot實現許可證生成與驗證

1. 申请许可证的场景。

当我们向客户出售商业软件时,我们经常需要对发布的软件实施一系列的控制措施,例如验证用户的身份、软件是否已过期失效,以及保存版权信息和开发者信息。考虑到许多应用场景可能处于离线环境中,无法依赖网络进行实时验证,我们还需要考虑如何在没有网络支持的情况下防止破解。总之,许可证采用HTTPS网站的证书和签名技术来证明当前用户是申请许可证的合法持有人,并防止恶意破解、伪造或篡改许可证,从而实现免费使用的目的。

为什么要使用许可证授权?

许可证的作用是什么?付费软件的许可证目的是为了防止用户免费使用软件。此外,许可证还应该具备以下功能:

  • 授权使用:明确用户需要满足的使用条件,如单一用户、多用户、企业内部使用、全球使用等,并通常限制可安装和激活的设备数量。
  • 使用期限:规定软件的使用期限,可能是永久许可或订阅模式。过期后,用户需要续订订阅才能继续使用软件。
  • 限制功能:根据许可级别,软件可以提供不同级别的功能,如标准版、高级版、企业版等。许可可以解锁相应版本的功能。
  • 版权保护:重申软件的知识产权所有权,并禁止未经授权的复制、分发、反编译、篡改或反向工程等版权侵权行为。
  • 法律保护:作为法律合同,许可建立了软件提供商与用户之间的法律关系,并明确了双方的权利和责任。如果违反协议,软件提供商有权采取法律行动追究法律责任。
  • 技术支持和升级服务:某些许可会规定用户是否享有免费技术支持、软件更新和维护服务,以及这些服务的有效时间。
  • 合规要求:对于特定行业或特定地区,许可需符合特定的法规、标准或认证要求。

总而言之,我们可以将许可证的功能总结为:

  • 控制用户对软件的访问权限
  • 认可软件所有者的版权
  • 规定软件的使用方法
2. 证书的准备工作

例如,如果私钥库的密码是“priwd123456”,公钥库的密码是“pubwd123456”,生成步骤如下所示:


    keytool -genkeypair -keysize 1024 -validity 3650 -alias "privateKey" -keystore "privateKeys.keystore" -storepass "pubwd123456" -keypass "priwd123456" -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"  # 生成密钥对,密钥长度为1024位,有效期为3650天,别名为“privateKey”,密钥库为“privateKeys.keystore”,库密码为“pubwd123456”,密钥密码为“priwd123456”,主体名信息为“CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN”。

    keytool -exportcert -alias "privateKey" -keystore "privateKeys.keystore" -storepass "pubwd123456" -file "certfile.cer"  # 导出证书,别名为“privateKey”,从密钥库“privateKeys.keystore”中导出,库密码为“pubwd123456”,输出文件为“certfile.cer”。

    keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore" -storepass "pubwd123456"  # 导入证书,别名为“publicCert”,从文件“certfile.cer”中导入,到密钥库“publicCerts.keystore”,库密码为“pubwd123456”。
3. 代码工程
这个实验的目的

实现许可证的生成及验证过程

pom.xml (Maven项目中的配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>SoftwareLicense</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>de.schlichtherle.truelicense</groupId>
            <artifactId>truelicense-core</artifactId>
            <version>1.33</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
生成许可

先获取服务器信息,再获取生成License.lic所需的信息。

package com.et.license.controller;  
import com.et.license.license.LicenseCheckModel;  
import com.et.license.license.LicenseCreatorParam;  
import com.et.license.service.LicenseCreatorService;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.web.bind.annotation.*;  
import java.util.Map;  

/**

* 许可创建控制器类,用于处理与许可证相关的请求。
 */
@RestController  
@RequestMapping("/license")  
public class LicenseCreatorController {  
    /**

* 自动注入的许可证创建服务。
     */
    @Autowired  
    private LicenseCreatorService licenseCreatorService;  

    /**

* 根据操作系统名称获取服务器信息。

* @param osName 操作系统名称

* @return 许可证检查模型对象
     */
    @GetMapping("/getServerInfos")  
    public LicenseCheckModel getServerInfos(@RequestParam String osName) {  
        return licenseCreatorService.getServerInfos(osName);  
    }  

    /**

* 生成许可证。

* @param param 许可证创建参数

* @return 包含生成的许可证信息的Map对象
     */
    @PostMapping("/generateLicense")  
    public Map<String, Object> generateLicense(@RequestBody LicenseCreatorParam param) {  
        return licenseCreatorService.generateLicense(param);  
    }  
}
package com.et.license.service;  
import com.et.license.license.LicenseCheckModel;  
import com.et.license.license.LicenseCreatorParam;  
import java.util.Map;  

public interface LicenseCreatorService {  

    LicenseCheckModel getServerInfos(String osName);  

    Map<String, Object> generateLicense(LicenseCreatorParam param);  
}

    包 源码 com.et.license.service.impl;  
    导入 包 com.et.license.license.*;  
    导入 包 com.et.license.service.LicenseCreatorService;  
    导入 包 org.springframework.beans.factory.annotation.Autowired;  
    导入 包 org.springframework.stereotype.Service;  
    导入 包 org.springframework.util.StringUtils;  
    导入 包 java.util.HashMap;  
    导入 包 java.util.Map;  

    @Service  
    类 LicenseCreatorServiceImpl 实现 LicenseCreatorService {  
        @Autowired  
        私有 LicenseConfig licenseConfig;  

        @Override  
        公有 LicenseCheckModel getServerInfos(字符串 osName) {  
            如果 (StringUtils.isEmpty(osName)) {  
                osName = System.getProperty("os.name");  
            }  
            osName = osName.toLowerCase();  
            抽象ServerInfos abstractServerInfos = null;  
            如果 (osName.startsWith("windows")) {  
                abstractServerInfos = 新的 WindowsServerInfos();  
            } 否则如果 (osName.startsWith("linux")) {  
                abstractServerInfos = 新的 LinuxServerInfos();  
            } 否则 {  
                abstractServerInfos = 新的 LinuxServerInfos();  
            }  
            return abstractServerInfos.getServerInfos();  
        }  

        @Override  
        公有 Map<字符串, Object> generateLicense(LicenseCreatorParam param) {  
            Map<字符串, Object> resultMap = 新的 HashMap<>(2);  
            如果 (StringUtils.isEmpty(param.getLicensePath())) {  
                param.setLicensePath(licenseConfig.getLicensePath());  
            }  
            LicenseCreator licenseCreator = 新的 LicenseCreator(param);  
            boolean result = licenseCreator.generateLicense();  
            如果 (result) {  
                resultMap.put("result", "ok");  
                resultMap.put("msg", param);  
            } 否则 {  
                resultMap.put("result", "error");  
                resultMap.put("msg", "生成失败!");  
            }  
            return resultMap;  
        }  
    }
安装及卸载许可
package com.et.license.license;  
import lombok.Data;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.boot.context.properties.ConfigurationProperties;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  

@Data  
@Configuration  
@ConfigurationProperties("license")  
@Slf4j  
public class LicenseConfig {  

    private String subject;  

    private String publicAlias;  

    private String storePass;  

    private String licensePath;  

    private String publicKeysStorePath;  

    @Bean(initMethod = "installLicense", destroyMethod = "unInstallLicense")  
    public LicenseVerify licenseVerify() {  
        return new LicenseVerify(subject, publicAlias, storePass, licensePath, publicKeysStorePath);  
    }  
}
校准证书
package com.et.license;  
import com.et.license.license.LicenseVerify;  
import org.junit.jupiter.api.Test;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.boot.test.context.SpringBootTest;  
@SpringBootTest  
class TrueLicenseApplicationTests {  
    @Autowired  
    private LicenseVerify licenseVerify;  

    @Test  
    void contextLoads() {  
        System.out.println("license valid:" + licenseVerify.verify());  
    }  
}

以上仅列出了一些关键代码片段。如需查看更多代码,访问以下代码仓库即可。

代码库
4. 测试

运行 Spring Boot 应用

查看服务器信息

创建一个名为 License.lic 的文件

请求的内容

{  
      "subject":"许可证演示",  
      "privateAlias":"私钥别名",  
      "keyPass":"密钥密码",  
      "storePass":"存储密码",  
      "licensePath":"/Users/liuhaihua/IdeaProjects/springboot-demo/SoftwareLicense/src/main/resources/license/license.lic",  
      "privateKeysStorePath":"/Users/liuhaihua/IdeaProjects/springboot-demo/SoftwareLicense/src/main/resources/license/privateKeys.keystore",  
      "issuedTime":"2020-10-10 00:00:01",  
      "expiryTime":"2025-10-09 23:59:59",  
      "consumerType":"消费类型",  
      "consumerAmount":1,  
      "description":"许可证演示",  
      "licenseCheckModel":{  
      "ipAddress": [  
      "192.168.0.100"  
      ],  
      "macAddress": [  
      "F0-18-98-50-71-5F"  
      ],  
      "cpuSerial": null,  
      "mainBoardSerial": null  
      }  
}

就是结果

安装证书文件
    2024-09-02 21:01:54.991 WARN 39586 --- [主线程] o.s.boot.StartupInfoLogger : InetAddress.getLocalHost().getHostName() 响应耗时 5003 毫秒。请验证您的网络配置(macOS 机器可能需要在 /etc/hosts 中添加条目)。
    2024-09-02 21:01:59.999 信息 39586 --- [主线程] com.et.license.DemoApplication : 在 bogon 上启动 DemoApplication,进程 ID 39586 (/Users/liuhaihua/IdeaProjects/springboot-demo/SoftwareLicense/target/classes,由 liuhaihua 在 /Users/liuhaihua/IdeaProjects/springboot-demo 启动)
    2024-09-02 21:02:00.001 信息 39586 --- [主线程] com.et.license.DemoApplication : 没有激活的配置文件,回退到默认配置文件:default
    2024-09-02 21:02:00.767 信息 39586 --- [主线程] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat 使用端口 8080 (http) 初始化
    2024-09-02 21:02:00.774 信息 39586 --- [主线程] o.apache.catalina.core.StandardService : 启动服务[Tomcat]
    2024-09-02 21:02:00.774 信息 39586 --- [主线程] org.apache.catalina.core.StandardEngine : 启动 Servlet 引擎[A=Apache Tomcat/9.0.31]
    2024-09-02 21:02:00.831 信息 39586 --- [主线程] o.a.c.c.C.[Tomcat].[localhost].[/] : 初始化 Spring 嵌入式的 WebApplicationContext
    2024-09-02 21:02:00.832 信息 39586 --- [主线程] o.s.web.context.ContextLoader : 根 WebApplicationContext 初始化完成,耗时 793 毫秒
    2024-09-02 21:02:01.128 信息 39586 --- [主线程] com.et.license.license.LicenseVerify : ------------------------------- 安装 -------------------------------
    2024-09-02 21:02:01.128 信息 39586 --- [主线程] com.et.license.license.LicenseVerify : 有效日期:2020-10-10 至 2025-10-09
    2024-09-02 21:02:01.210 信息 39586 --- [主线程] o.s.s.concurrent.ThreadPoolTaskExecutor : 初始化 ExecutorService 'applicationTaskExecutor'
    2024-09-02 21:02:01.344 信息 39586 --- [主线程] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat 在端口 8080 (http) 上启动,上下文路径为空字符串
    2024-09-02 21:02:01.347 信息 39586 --- [主线程] com.et.license.DemoApplication : DemoApplication 启动耗时 16.649 秒,JVM 运行时间为 22.127 秒
    2024-09-02 21:09:41.535 信息 39586 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : 初始化 Spring DispatcherServlet 'dispatcherServlet'
    2024-09-02 21:09:41.538 信息 39586 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : 初始化 Servlet 'dispatcherServlet'
    2024-09-02 21:09:41.588 信息 39586 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : 初始化完成,耗时 50 毫秒
校准证明

执行测试案例

2024-09-02 21:17:17.212 INFO 39937 --- [main] com.et.license.license.LicenseVerify : 证书的有效期限:2020-10-10 00:00:01 - 2025-10-09 23:59:59  
证书有效: 是,
5. 参考资料
點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消