草庐IT

springboot实现License证书的授权和许可到期验证

想养一只! 2023-04-03 原文

前言

在客户服务器部署软件项目后,为了项目版权管控或者对项目进行授权收费处理的,就需要实现项目的授权和许可验证。

在这里讲解的是使用 license证书 的形式实现授权和许可验证(已通过测试)。
主要是通过 IP地址、MAC地址、CPU序列号、主板序列号 服务器硬件信息生成一个License证书,同时可以设置生效时间与失效时间,控制项目到期之后项目不可用。

实现思路

license授权机制的原理

1、生成密钥对,包含私钥和公钥。
2、授权者保留私钥,使用私钥对授权信息诸如使用截止日期,mac 地址等内容生成 license 签名证书。
3、公钥给使用者,放在代码中使用,用于验证 license 签名证书是否符合使用条件。

实现流程

1、使用JDK自带的 keytool 生成密钥对(生成私钥和公钥两个文件)
2、License服务端获取服务器硬件信息
3、License服务器根据服务器硬件信息和私钥文件加密生成 License.lic 文件,也就是License证书。
4、License客户端安装License证书并生效和到期日期进行校验

实现步骤

一、使用KeyTool生成密匙对

1、自己本地随便找个位置创建一个文件夹,我这里创建了名为 License 的文件夹

2、进入到该文件中,在上面的路径中输入cmd并回车,会打开命令窗口

3、在命令窗口中依次输入以下命令

keytool -genkey -keysize 1024 -keyalg DSA -validity 3650 -alias "privateKey" -keystore "privateKeys.keystore" -storepass "ljh521548" -keypass "ljh521548" -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN"

# 导出命令
keytool -exportcert -alias "privateKey" -keystore "privateKeys.keystore" -storepass "ljh521548" -file "certfile.cer"
 
#导入命令
keytool -import -alias "publicCert" -file "certfile.cer" -keystore "publicCerts.keystore" -storepass "ljh521548"

命令参数说明:

keysize 密钥长度
keyalg  加密方式 
validity 私钥的有效期(单位:天)
alias 私钥别称
keystore 指定私钥库文件的名称 (生成在当前目录)
storepass 指定私钥库的密码 (keystore 文件存储密码)
keypass 指定别名条目的密码 (私钥加解密密码)
dname 证书个人信息
CN 为你的姓名
OU 为你的组织单位名称
O 为你的组织名称
L 为你所在的城市名称
ST 为你所在的省份名称
C 为你的国家名称


然后可以看到以下三个文件:

privateKeys.keystore(私钥)提供给生成证书使用(自己保留)

publicCerts. keystore(公钥)提供给证书认证使用(给客户使用)

certfile.cer后续步骤用不到,可以删除。

其他可能使用到的命令

# 删除
keytool -delete -alias privateKey -keystore "privateKeys.keystore" -storepass "ljh521548"

# 查看
keytool -list -v -keystore zuiyuPrivateKeys.keystore -storepass "ljh521548"

二、License服务端获取服务器信息和生成License证书

源码:https://gitee.com/sshmily/license-service

1、启动后通过 /api/license/getServerInfos/{osName} 接口获取到服务器的硬件地址。
如果是windows系统osName参数就输入windows,Linux系统osName参数就输入Linux。

2、使用服务器的硬件信息和第一步生成的私钥生成License证书

使用 /api/license/generateLicense 接口生成证书。

请求参数示例

{
    "subject": "license_ljh", //主题名
    "privateAlias": "privateKey", //私钥别名
    "keyPass": "ljh521548", //私钥密码
    "storePass": "ljh521548", //密钥库密码
    "licensePath": "D:/License/license.lic", //生成证书的存储位置
    "privateKeysStorePath": "D:/License/privateKeys.keystore", //私钥的存储位置
    "issuedTime": "2022-12-09 00:00:00", //开始生效时间
    "expiryTime": "2099-12-09 00:00:00", //证书到期时间
    "consumerType": "user",  //用户类型
    "consumerAmount": 1, //用户数量
    "description": "这是证书描述信息", //描述信息
    "licenseCheckModel": {  //licenseCheckModel 第一步获取到的服务器硬件信息
        "ipAddress": [
            ""
        ],
        "macAddress": [
            ""
        ],
        "cpuSerial": "",
        "mainBoardSerial": ""
    }
}

三、客户端安装证书并校验时间

源码:https://gitee.com/sshmily/license-client

源码拿到本地后主要是修改yml文件配置即可,其他的代码都有说明

license:
  subject: license_ljh #主题名
  publicAlias: publicCert  #公钥别名
  storePass: ljh21548 #密钥库密码
  licensePath: D:/License/license.lic  #license证书存放位置
  publicKeysStorePath: D:/License/publicCerts.keystore  #公钥文件存放位置
  uploadPath: D:/LicenseDemo/

测试

1、证书过期

当证书过期的时候启动客户端控制台会提示 exc.licenseHasExpired 错误,说明证书已经过期的。

这个时候访问项目就会出现以下提示

2、证书有效


有关springboot实现License证书的授权和许可到期验证的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  5. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  6. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  7. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  8. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

随机推荐