创建微服务项目名称: cloud-license-client,版本:2.5.5,模拟给客户部署的应用。
1.1pom.xml1.2 application.properties4.0.0 org.springframework.boot spring-boot-starter-parent2.5.5 com.example demo0.0.1-SNAPSHOT demo Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starterorg.springframework.boot spring-boot-starter-testtest org.springframework.boot spring-boot-starter-webde.schlichtherle.truelicense truelicense-core1.33 net.sourceforge.nekohtml nekohtml1.9.18 org.projectlombok lombokorg.apache.commons commons-lang33.7 cn.hutool hutool-all5.0.6 org.springframework.boot spring-boot-maven-pluginorg.apache.maven.plugins maven-resources-plugin2.4.3
server.port=8082 #启用优雅关机 server.shutdown=graceful #缓冲10秒 spring.lifecycle.timeout-per-shutdown-phase=10s #License相关配置 license.subject=license_demo license.publicAlias=publicCert license.storePass=public_password12345 license.licensePath=D:/workspace/gitee/spring-boot2-license/license/license.lic license.publicKeysStorePath=D:/workspace/gitee/spring-boot2-license/license/publicCerts.keystore json.class.type=jackson1.3 License校验类
package com.example.license;
import com.example.entity.LicenseVerifyParam;
import com.example.helper.LoggerHelper;
import com.example.helper.ParamInitHelper;
import com.example.model.LicenseCustomManager;
import com.example.model.LicenseResult;
import com.example.utils.DateUtils;
import de.schlichtherle.license.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.prefs.Preferences;
@Slf4j
public class LicenseVerify {
public synchronized LicenseContent install(LicenseVerifyParam param){
LicenseContent result = null;
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//1. 安装证书
try{
LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
licenseManager.uninstall();
result = licenseManager.install(new File(param.getLicensePath()));
log.info(MessageFormat.format("证书安装成功,证书有效期:{0} - {1}",format.format(result.getNotBefore()),format.format(result.getNotAfter())));
}catch (Exception e){
log.error("证书安装失败!",e);
}
return result;
}
public boolean verify(LicenseVerifyParam param){
LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//2. 校验证书
try {
LicenseContent licenseContent = licenseManager.verify();
// System.out.println(licenseContent.getSubject());
log.info(MessageFormat.format("证书校验通过,证书有效期:{0} - {1}",format.format(licenseContent.getNotBefore()),format.format(licenseContent.getNotAfter())));
return true;
}catch (Exception e){
log.error("证书校验失败!",e);
return false;
}
}
private LicenseParam initLicenseParam(LicenseVerifyParam param){
Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class
,param.getPublicKeysStorePath()
,param.getPublicAlias()
,param.getStorePass()
,null);
return new DefaultLicenseParam(param.getSubject()
,preferences
,publicStoreParam
,cipherParam);
}
}
1.4 添加Listener,用于启动项目时安装License证书
package com.example.license; import com.example.entity.LicenseVerifyParam; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; @Slf4j @Component public class LicenseCheckListener implements ApplicationListener1.5 添加拦截器,用于在登录的时候校验License证书{ @Value("${license.subject}") private String subject; @Value("${license.publicAlias}") private String publicAlias; @Value("${license.storePass}") private String storePass; @Value("${license.licensePath}") private String licensePath; @Value("${license.publicKeysStorePath}") private String publicKeysStorePath; @Override public void onApplicationEvent(ContextRefreshedEvent event) { //root application context 没有parent ApplicationContext context = event.getApplicationContext().getParent(); if(context == null){ if(StringUtils.isNotBlank(licensePath)){ log.info("++++++++ 开始安装证书 ++++++++"); LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); LicenseVerify licenseVerify = new LicenseVerify(); //安装证书 licenseVerify.install(param); log.info("++++++++ 证书安装结束 ++++++++"); } } } public LicenseVerifyParam getVerifyParam(){ LicenseVerifyParam param = new LicenseVerifyParam(); param.setSubject(subject); param.setPublicAlias(publicAlias); param.setStorePass(storePass); param.setLicensePath(licensePath); param.setPublicKeysStorePath(publicKeysStorePath); return param; } }
package com.example.config;
import com.example.license.LicenseCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.example"})
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
public LicenseCheckInterceptor licenseCheckInterceptor;
public InterceptorConfig() {
System.out.println("============InterceptorConfig 已装载===========");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("
public class LicenseManagerHolder {
private static LicenseManager licenseManager;
public static synchronized LicenseManager getLicenseManager(LicenseParam licenseParam) {
if(null == licenseManager) {
try {
licenseManager = new LicenseManager(licenseParam);
} catch (Exception e) {
e.printStackTrace();
}
}
return licenseManager;
}
public static LicenseManager getInstance(LicenseParam initLicenseParam) {
return new LicenseManager(initLicenseParam);
}
}
1.7 创建LicenseVerifyParam类
package com.example.entity;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
public class LicenseVerifyParam {
//
// private String subject;
//
//
// private String publicAlias;
//
//
// private String storePass;
//
//
// private String licensePath;
//
//
// private String publicKeysStorePath;
@Value("${license.subject}")
private String subject;
@Value("${license.publicAlias}")
private String publicAlias;
@Value("${license.storePass}")
private String storePass;
@Value("${license.licensePath}")
private String licensePath;
@Value("${license.publicKeysStorePath}")
private String publicKeysStorePath;
public LicenseVerifyParam() {
}
public LicenseVerifyParam(String subject, String publicAlias, String storePass, String licensePath, String publicKeysStorePath) {
this.subject = subject;
this.publicAlias = publicAlias;
this.storePass = storePass;
this.licensePath = licensePath;
this.publicKeysStorePath = publicKeysStorePath;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPublicAlias() {
return publicAlias;
}
public void setPublicAlias(String publicAlias) {
this.publicAlias = publicAlias;
}
public String getStorePass() {
return storePass;
}
public void setStorePass(String storePass) {
this.storePass = storePass;
}
public String getLicensePath() {
return licensePath;
}
public void setLicensePath(String licensePath) {
this.licensePath = licensePath;
}
public String getPublicKeysStorePath() {
return publicKeysStorePath;
}
public void setPublicKeysStorePath(String publicKeysStorePath) {
this.publicKeysStorePath = publicKeysStorePath;
}
@Override
public String toString() {
return "LicenseVerifyParam{" +
"subject='" + subject + ''' +
", publicAlias='" + publicAlias + ''' +
", storePass='" + storePass + ''' +
", licensePath='" + licensePath + ''' +
", publicKeysStorePath='" + publicKeysStorePath + ''' +
'}';
}
public LicenseVerifyParam getVerifyParam() {
LicenseVerifyParam param = new LicenseVerifyParam();
param.setSubject(subject);
param.setPublicAlias(publicAlias);
param.setStorePass(storePass);
param.setLicensePath(licensePath);
param.setPublicKeysStorePath(publicKeysStorePath);
return param;
}
}
1.8 创建CustomKeyStoreParam类
package com.example.license;
import de.schlichtherle.license.AbstractKeyStoreParam;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CustomKeyStoreParam extends AbstractKeyStoreParam {
private String storePath;
private String alias;
private String storePwd;
private String keyPwd;
public CustomKeyStoreParam(Class clazz, String resource, String alias, String storePwd, String keyPwd) {
super(clazz, resource);
this.storePath = resource;
this.alias = alias;
this.storePwd = storePwd;
this.keyPwd = keyPwd;
}
@Override
public String getAlias() {
return alias;
}
@Override
public String getStorePwd() {
return storePwd;
}
@Override
public String getKeyPwd() {
return keyPwd;
}
@Override
public InputStream getStream() throws IOException {
return new FileInputStream(new File(storePath));
}
}
创建FastLicense 自定义注解
package com.example.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FastLicense {
String[] verifies() default{};
}
1.9 创建Controller模拟登录操作
package com.example.controller;
import com.example.annotation.FastLicense;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@CrossOrigin
@RestController
public class LoginController {
@GetMapping(value = "/login")
@FastLicense
public Map test(@RequestParam(required = true) String loginName, @RequestParam(required = true) String password){
Map result = new HashMap<>(1);
log.info(MessageFormat.format("登录名称:{0},密码:{1}",loginName,password));
//模拟登录
log.info("模拟登录被拦截检查证书可用性");
result.put("code",200);
return result;
}
}
模拟安装证书失败
安装证书成功



