mirror of
				https://github.com/NotoChen/Jetbrains-Help.git
				synced 2025-10-31 17:08:30 +08:00 
			
		
		
		
	append license server
This commit is contained in:
		
							parent
							
								
									882dbfc126
								
							
						
					
					
						commit
						f4a7d653c5
					
				|  | @ -1,9 +1,11 @@ | |||
| package com.jetbrains.help; | ||||
| 
 | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.io.IoUtil; | ||||
| import cn.hutool.core.net.Ipv4Util; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.hutool.crypto.SecureUtil; | ||||
| import cn.hutool.extra.spring.SpringUtil; | ||||
| import com.jetbrains.help.context.*; | ||||
| import lombok.SneakyThrows; | ||||
|  | @ -17,6 +19,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; | |||
| import org.springframework.scheduling.annotation.Scheduled; | ||||
| 
 | ||||
| import java.net.InetAddress; | ||||
| import java.security.cert.Certificate; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| 
 | ||||
|  | @ -37,7 +40,6 @@ public class JetbrainsHelpApplication { | |||
|         PluginsContextHolder.init(); | ||||
|         CertificateContextHolder.init(); | ||||
|         AgentContextHolder.init(); | ||||
| 
 | ||||
|         InetAddress localHost = InetAddress.getLocalHost(); | ||||
|         String address = CharSequenceUtil.format("http://{}:{}", localHost.getHostAddress(), SpringUtil.getProperty("server.port")); | ||||
|         String runSuccessWarn = "\n====================================================================================\n" + | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ public class AgentContextHolder { | |||
|     public static void init() { | ||||
|         log.info("Agent context init loading..."); | ||||
|         jaNetfilterZipFile = FileTools.getFileOrCreat(JA_NETFILTER_FILE_PATH + ".zip"); | ||||
|         if (!FileTools.fileExists(JA_NETFILTER_FILE_PATH)) { | ||||
|         if (FileTools.fileNotExists(JA_NETFILTER_FILE_PATH)) { | ||||
|             unzipJaNetfilter(); | ||||
|             if (!powerConfHasInit()) { | ||||
|                 log.info("Agent config init loading..."); | ||||
|  | @ -75,14 +75,27 @@ public class AgentContextHolder { | |||
| 
 | ||||
|     @SneakyThrows | ||||
|     private static String generatePowerConfigRule() { | ||||
|         X509Certificate crt = (X509Certificate) KeyUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.crtFile())); | ||||
|         RSAPublicKey publicKey = (RSAPublicKey) PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.publicKeyFile())); | ||||
|         RSAPublicKey rootPublicKey = (RSAPublicKey) PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.rootKeyFile())); | ||||
|         StringBuilder result = new StringBuilder(); | ||||
|         X509Certificate crt = (X509Certificate) KeyUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.getCrtFile())); | ||||
|         X509Certificate licenseCrt = (X509Certificate) KeyUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.getLicenseCrtFile())); | ||||
|         RSAPublicKey publicKey = (RSAPublicKey) PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.getPublicKeyFile())); | ||||
|         RSAPublicKey rootPublicKey = (RSAPublicKey) PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.getRootKeyFile())); | ||||
|         RSAPublicKey rootLicensePublicKey = (RSAPublicKey) PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.getRootLicenseKeyFile())); | ||||
|         BigInteger x = new BigInteger(1, crt.getSignature()); | ||||
|         BigInteger y = BigInteger.valueOf(65537L); | ||||
|         BigInteger y = rootPublicKey.getPublicExponent(); | ||||
|         BigInteger z = rootPublicKey.getModulus(); | ||||
|         BigInteger r = x.modPow(publicKey.getPublicExponent(), publicKey.getModulus()); | ||||
|         return CharSequenceUtil.format("EQUAL,{},{},{}->{}", x, y, z, r); | ||||
|         result.append("; Activation Code").append("\n") | ||||
|                 .append(CharSequenceUtil.format("EQUAL,{},{},{}->{}", x, y, z, r)) | ||||
|                 .append("\n"); | ||||
|         x = new BigInteger(1, licenseCrt.getSignature()); | ||||
|         z = rootLicensePublicKey.getModulus(); | ||||
|         y = rootLicensePublicKey.getPublicExponent(); | ||||
|         r = x.modPow(publicKey.getPublicExponent(), publicKey.getModulus()); | ||||
|         result.append("; License Server").append("\n") | ||||
|                 .append(CharSequenceUtil.format("EQUAL,{},{},{}->{}", x, y, z, r)) | ||||
|                 .append("\n"); | ||||
|         return result.toString(); | ||||
|     } | ||||
| 
 | ||||
|     private static String generatePowerConfigStr(String ruleValue) { | ||||
|  |  | |||
|  | @ -3,10 +3,12 @@ package com.jetbrains.help.context; | |||
| import cn.hutool.core.date.DateField; | ||||
| import cn.hutool.core.date.DateUtil; | ||||
| import cn.hutool.core.io.FileUtil; | ||||
| import cn.hutool.core.io.IoUtil; | ||||
| import cn.hutool.crypto.PemUtil; | ||||
| import cn.hutool.crypto.SecureUtil; | ||||
| import com.jetbrains.help.util.FileTools; | ||||
| import lombok.AccessLevel; | ||||
| import lombok.Getter; | ||||
| import lombok.NoArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.bouncycastle.asn1.x500.X500Name; | ||||
|  | @ -27,29 +29,47 @@ import java.security.cert.Certificate; | |||
| import java.security.cert.CertificateEncodingException; | ||||
| import java.security.cert.CertificateException; | ||||
| 
 | ||||
| /** | ||||
|  * <a href="https://github.com/JetBrains/marketplace-makemecoffee-plugin/blob/master/src/main/java/com/company/license/CheckLicense.java">源证书来源</a> | ||||
|  */ | ||||
| @Slf4j | ||||
| @NoArgsConstructor(access = AccessLevel.PRIVATE) | ||||
| public class CertificateContextHolder { | ||||
| 
 | ||||
|     private static final String ROOT_KEY_FILE_NAME = "external/certificate/root.key"; | ||||
|     private static final String ROOT_LICENSE_KEY_FILE_NAME = "external/certificate/license-root.key"; | ||||
|     private static final String PRIVATE_KEY_FILE_NAME = "external/certificate/private.key"; | ||||
|     private static final String PUBLIC_KEY_FILE_NAME = "external/certificate/public.key"; | ||||
|     private static final String CET_FILE_NAME = "external/certificate/ca.crt"; | ||||
|     private static final String LICENSE_CET_FILE_NAME = "external/certificate/license-ca.crt"; | ||||
|     public static final String SERVER_UID = "cikaros.top"; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File rootKeyFile; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File rootLicenseKeyFile; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File privateKeyFile; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File publicKeyFile; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File crtFile; | ||||
| 
 | ||||
|     @Getter | ||||
|     private static File licenseCrtFile; | ||||
| 
 | ||||
|     public static void init() { | ||||
|         log.info("certificate context init loading..."); | ||||
|         rootKeyFile = FileTools.getFileOrCreat(ROOT_KEY_FILE_NAME); | ||||
|         if (!FileTools.fileExists(PRIVATE_KEY_FILE_NAME) | ||||
|                 || !FileTools.fileExists(PUBLIC_KEY_FILE_NAME) | ||||
|                 || !FileTools.fileExists(CET_FILE_NAME)) { | ||||
|         rootLicenseKeyFile = FileTools.getFileOrCreat(ROOT_LICENSE_KEY_FILE_NAME); | ||||
|         if (FileTools.fileNotExists(PRIVATE_KEY_FILE_NAME) | ||||
|                 || FileTools.fileNotExists(PUBLIC_KEY_FILE_NAME) | ||||
|                 || FileTools.fileNotExists(CET_FILE_NAME) | ||||
|                 || FileTools.fileNotExists(LICENSE_CET_FILE_NAME)) { | ||||
|             log.info("certificate context generate loading..."); | ||||
|             generateCertificate(); | ||||
|             log.info("certificate context generate success!"); | ||||
|  | @ -57,27 +77,11 @@ public class CertificateContextHolder { | |||
|             privateKeyFile = FileTools.getFileOrCreat(PRIVATE_KEY_FILE_NAME); | ||||
|             publicKeyFile = FileTools.getFileOrCreat(PUBLIC_KEY_FILE_NAME); | ||||
|             crtFile = FileTools.getFileOrCreat(CET_FILE_NAME); | ||||
|             licenseCrtFile = FileTools.getFileOrCreat(LICENSE_CET_FILE_NAME); | ||||
|         } | ||||
|         log.info("certificate context init success !"); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public static File rootKeyFile() { | ||||
|         return CertificateContextHolder.rootKeyFile; | ||||
|     } | ||||
| 
 | ||||
|     public static File privateKeyFile() { | ||||
|         return CertificateContextHolder.privateKeyFile; | ||||
|     } | ||||
| 
 | ||||
|     public static File publicKeyFile() { | ||||
|         return CertificateContextHolder.publicKeyFile; | ||||
|     } | ||||
| 
 | ||||
|     public static File crtFile() { | ||||
|         return CertificateContextHolder.crtFile; | ||||
|     } | ||||
| 
 | ||||
|     public static void generateCertificate() { | ||||
|         KeyPair keyPair = SecureUtil.generateKeyPair("RSA", 4096); | ||||
|         PrivateKey privateKey = keyPair.getPrivate(); | ||||
|  | @ -86,16 +90,8 @@ public class CertificateContextHolder { | |||
|         PemUtil.writePemObject("PRIVATE KEY", privateKey.getEncoded(), FileUtil.getWriter(privateKeyFile, StandardCharsets.UTF_8, false)); | ||||
|         publicKeyFile = FileTools.getFileOrCreat(PUBLIC_KEY_FILE_NAME); | ||||
|         PemUtil.writePemObject("PUBLIC KEY", publicKey.getEncoded(), FileUtil.getWriter(publicKeyFile, StandardCharsets.UTF_8, false)); | ||||
|         JcaX509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder( | ||||
|                 new X500Name("CN=JetProfile CA"), | ||||
|                 BigInteger.valueOf(System.currentTimeMillis()), | ||||
|                 DateUtil.yesterday(), | ||||
|                 DateUtil.date().offset(DateField.YEAR, 100), | ||||
|                 new X500Name("CN=Jetbrains-Help"), | ||||
|                 SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); | ||||
|         try { | ||||
|             ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(privateKey); | ||||
|             Certificate certificate = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateBuilder.build(signer)); | ||||
|             Certificate certificate = generateCertificate(keyPair,"JetProfile CA","Jetbrains-Help"); | ||||
|             crtFile = FileTools.getFileOrCreat(CET_FILE_NAME); | ||||
|             PemUtil.writePemObject("CERTIFICATE", certificate.getEncoded(), FileUtil.getWriter(crtFile, StandardCharsets.UTF_8, false)); | ||||
|         } catch (OperatorCreationException e) { | ||||
|  | @ -105,7 +101,33 @@ public class CertificateContextHolder { | |||
|         } catch (CertificateException e) { | ||||
|             throw new IllegalArgumentException("The certificate read exception", e); | ||||
|         } | ||||
|         //TODO 创建License Servers CA | ||||
|         try { | ||||
|             Certificate certificate = generateCertificate(keyPair,"License Servers CA",String.format("%s.lsrv.jetbrains.com", SERVER_UID)); | ||||
|             licenseCrtFile = FileTools.getFileOrCreat(LICENSE_CET_FILE_NAME); | ||||
|             PemUtil.writePemObject("CERTIFICATE", certificate.getEncoded(), FileUtil.getWriter(licenseCrtFile, StandardCharsets.UTF_8, false)); | ||||
|         } catch (OperatorCreationException e) { | ||||
|             throw new IllegalArgumentException("Certificate operator creation exception", e); | ||||
|         } catch (CertificateEncodingException e) { | ||||
|             throw new IllegalArgumentException("The certificate encoding exception", e); | ||||
|         } catch (CertificateException e) { | ||||
|             throw new IllegalArgumentException("The certificate read exception", e); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static Certificate generateCertificate(KeyPair keyPair, String issuer, String subject) throws OperatorCreationException, CertificateException { | ||||
|         PrivateKey privateKey = keyPair.getPrivate(); | ||||
|         PublicKey publicKey = keyPair.getPublic(); | ||||
|         JcaX509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder( | ||||
|                 new X500Name(String.format("CN=%s", issuer)), | ||||
|                 BigInteger.valueOf(System.currentTimeMillis()), | ||||
|                 DateUtil.yesterday(), | ||||
|                 DateUtil.date().offset(DateField.YEAR, 100), | ||||
|                 new X500Name(String.format("CN=%s", subject)), | ||||
|                 SubjectPublicKeyInfo.getInstance(publicKey.getEncoded())); | ||||
|         ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(privateKey); | ||||
|         return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateBuilder.build(signer)); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,20 +1,24 @@ | |||
| package com.jetbrains.help.context; | ||||
| 
 | ||||
| import cn.hutool.core.codec.Base64; | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import cn.hutool.core.io.IoUtil; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import cn.hutool.core.util.IdUtil; | ||||
| import cn.hutool.core.util.XmlUtil; | ||||
| import cn.hutool.crypto.PemUtil; | ||||
| import cn.hutool.crypto.SecureUtil; | ||||
| import cn.hutool.crypto.SignUtil; | ||||
| import cn.hutool.crypto.asymmetric.Sign; | ||||
| import cn.hutool.json.JSONUtil; | ||||
| import lombok.AccessLevel; | ||||
| import lombok.Builder; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.w3c.dom.Document; | ||||
| import org.w3c.dom.Node; | ||||
| 
 | ||||
| import java.math.BigInteger; | ||||
| import java.security.PrivateKey; | ||||
| import java.security.PublicKey; | ||||
| import java.security.cert.Certificate; | ||||
|  | @ -22,7 +26,7 @@ import java.security.cert.CertificateEncodingException; | |||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| import static cn.hutool.crypto.asymmetric.SignAlgorithm.SHA1withRSA; | ||||
| import static cn.hutool.crypto.asymmetric.SignAlgorithm.*; | ||||
| 
 | ||||
| @Slf4j | ||||
| @NoArgsConstructor(access = AccessLevel.PRIVATE) | ||||
|  | @ -43,9 +47,9 @@ public class LicenseContextHolder { | |||
|                 .setProducts(products); | ||||
|         String licensePartJson = JSONUtil.toJsonStr(licensePart); | ||||
|         String licensePartBase64 = Base64.encode(licensePartJson); | ||||
|         PrivateKey privateKey = PemUtil.readPemPrivateKey(IoUtil.toStream(CertificateContextHolder.privateKeyFile())); | ||||
|         PublicKey publicKey = PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.publicKeyFile())); | ||||
|         Certificate certificate = SecureUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.crtFile())); | ||||
|         PrivateKey privateKey = PemUtil.readPemPrivateKey(IoUtil.toStream(CertificateContextHolder.getPrivateKeyFile())); | ||||
|         PublicKey publicKey = PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.getPublicKeyFile())); | ||||
|         Certificate certificate = SecureUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.getCrtFile())); | ||||
|         Sign sign = SignUtil.sign(SHA1withRSA, privateKey.getEncoded(), publicKey.getEncoded()); | ||||
|         String signatureBase64 = Base64.encode(sign.sign(licensePartJson)); | ||||
|         String certBase64; | ||||
|  | @ -74,4 +78,147 @@ public class LicenseContextHolder { | |||
|         private String paidUpTo; | ||||
|     } | ||||
| 
 | ||||
|     public static String obtainTicket(ObtainTicketRequest request) { | ||||
|         PrivateKey privateKey = PemUtil.readPemPrivateKey(IoUtil.toStream(CertificateContextHolder.getPrivateKeyFile())); | ||||
|         PublicKey publicKey = PemUtil.readPemPublicKey(IoUtil.toStream(CertificateContextHolder.getPublicKeyFile())); | ||||
|         Certificate cert = SecureUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.getCrtFile())); | ||||
|         Certificate licenseCert = SecureUtil.readX509Certificate(IoUtil.toStream(CertificateContextHolder.getLicenseCrtFile())); | ||||
|         ObtainTicketResponse response = obtainTicket(privateKey, publicKey, cert, licenseCert, request); | ||||
|         Document document = XmlUtil.beanToXml(response); | ||||
|         String result = XmlUtil.toStr(document, "UTF-8", true, true); | ||||
|         //!important 必须去除XML中所有的换行和空格,即紧凑模式 | ||||
|         result = result.replaceAll("[\n ]", ""); | ||||
|         Sign sign = SignUtil.sign(SHA1withRSA, privateKey.getEncoded(), publicKey.getEncoded()); | ||||
|         String sign64 = Base64.encode(sign.sign(result)); | ||||
|         String licenseCertBase64; | ||||
|         try { | ||||
|             licenseCertBase64 = Base64.encode(licenseCert.getEncoded()); | ||||
|         } catch (CertificateEncodingException e) { | ||||
|             throw new IllegalArgumentException("Certificate extraction failed", e); | ||||
|         } | ||||
|         //<!--  SHA1withRSA-{下面 xml 主体内容的签名 }-{license Server CA}  --> | ||||
|         String signRes = String.format("<!-- SHA1withRSA-%s-%s -->", sign64, licenseCertBase64); | ||||
|         return signRes + "\n" + result; | ||||
|     } | ||||
| 
 | ||||
|     public static ObtainTicketResponse obtainTicket(PrivateKey privateKey, PublicKey publicKey, Certificate cert, Certificate licenseCert, ObtainTicketRequest request) { | ||||
|         String certBase64; | ||||
|         String licenseCertBase64; | ||||
|         try { | ||||
|             certBase64 = Base64.encode(cert.getEncoded()); | ||||
|             licenseCertBase64 = Base64.encode(licenseCert.getEncoded()); | ||||
|         } catch (CertificateEncodingException e) { | ||||
|             throw new IllegalArgumentException("Certificate extraction failed", e); | ||||
|         } | ||||
| 
 | ||||
|         long time = System.currentTimeMillis(); | ||||
|         long leaseTime = time + (1000L * 60 * 60 * 24 * 365); | ||||
|         //{失效时间戳}:{serverUid} | ||||
|         String serverLease = String.format("%d:%s", leaseTime, CertificateContextHolder.SERVER_UID); | ||||
| 
 | ||||
|         Sign sign = SignUtil.sign(SHA1withRSA, privateKey.getEncoded(), publicKey.getEncoded()); | ||||
|         String signatureBase64 = Base64.encode(sign.sign(String.format("%d:%s", time, request.getMachineId()))); | ||||
|         //{时间戳}:{客户端提交的machineId}:SHA1withRSA:{对({时间戳}:{客户端提交的machineId})的签名}:{license Server CA} | ||||
|         String confirmationStamp = String.format("%d:%s:SHA1withRSA:%s:%s", | ||||
|                 time, request.getMachineId(), signatureBase64, licenseCertBase64); | ||||
| 
 | ||||
|         sign = SignUtil.sign(SHA512withRSA, privateKey.getEncoded(), publicKey.getEncoded()); | ||||
|         byte[] bytes = sign.sign(serverLease); | ||||
|         signatureBase64 = Base64.encode(bytes); | ||||
|         //SHA512withRSA-{对「serverLease」的值进行签名}-{JetProfile CA} | ||||
|         String leaseSignature = String.format("SHA512withRSA-%s-%s", signatureBase64, certBase64); | ||||
| //        String leaseSignature = new BigInteger(1,bytes).toString(); | ||||
|         return ObtainTicketResponse.builder() | ||||
|                 .action(Action.NONE) | ||||
|                 .responseCode(ResponseCode.OK) | ||||
|                 .message(ResponseCode.OK.name()) | ||||
|                 .ticketId("20") | ||||
|                 .ticketProperties(String.format("licensee=%s\tlicenseType=4\tmetadata=0120230914PSAX000005", request.getUserName())) | ||||
|                 .validationPeriod(71829000L) | ||||
|                 .validationDeadlinePeriod(-1) | ||||
|                 .prolongationPeriod(63462000L)//有效期 | ||||
|                 .salt(request.getSalt()) | ||||
|                 .serverUid(CertificateContextHolder.SERVER_UID) | ||||
|                 .serverLease(serverLease) | ||||
|                 .confirmationStamp(confirmationStamp) | ||||
|                 .leaseSignature(leaseSignature) | ||||
|                 .build(); | ||||
|     } | ||||
| 
 | ||||
|     public enum Action { | ||||
|         NONE, | ||||
|     } | ||||
| 
 | ||||
|     public enum ResponseCode { | ||||
|         OK | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取认证票据 | ||||
|      * | ||||
|      * @author Cikaros | ||||
|      * @date 2023/11/1 | ||||
|      */ | ||||
|     @Data | ||||
|     @Builder | ||||
|     public static class ObtainTicketResponse { | ||||
|         @Builder.Default | ||||
|         private Action action = Action.NONE; | ||||
|         private String confirmationStamp; | ||||
|         private String leaseSignature; | ||||
|         @Builder.Default | ||||
|         private String message = ""; | ||||
|         @Builder.Default | ||||
|         private Long prolongationPeriod = 1800000L; | ||||
|         @Builder.Default | ||||
|         private ResponseCode responseCode = ResponseCode.OK; | ||||
|         private String salt; | ||||
|         private String serverLease; | ||||
|         private String serverUid; | ||||
|         @Builder.Default | ||||
|         private String ticketId = "1"; | ||||
|         private String ticketProperties; | ||||
|         @Builder.Default | ||||
|         private Integer validationDeadlinePeriod = -1; | ||||
|         @Builder.Default | ||||
|         private Long validationPeriod = 1800000L; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @author Cikaros | ||||
|      * @date 2023/10/20 | ||||
|      */ | ||||
|     @Data | ||||
|     public static class ObtainTicketRequest { | ||||
| 
 | ||||
|         private String ideProductCode; | ||||
| 
 | ||||
|         private Boolean empty; | ||||
| 
 | ||||
|         private String buildDate; | ||||
| 
 | ||||
|         private String buildNumber; | ||||
| 
 | ||||
|         private Integer clientVersion; | ||||
| 
 | ||||
|         private String hostName; | ||||
| 
 | ||||
|         private String machineId; | ||||
| 
 | ||||
|         private String productCode; | ||||
| 
 | ||||
|         private String productFamilyId; | ||||
| 
 | ||||
|         private String salt; | ||||
| 
 | ||||
|         private Boolean secure; | ||||
| 
 | ||||
|         private String userName; | ||||
| 
 | ||||
|         private String version; | ||||
| 
 | ||||
|         private Long versionNumber; | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,22 @@ | |||
| package com.jetbrains.help.controller; | ||||
| 
 | ||||
| import com.jetbrains.help.context.LicenseContextHolder; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.http.ResponseEntity; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.ResponseBody; | ||||
| 
 | ||||
| @Controller | ||||
| @RequestMapping("/rpc") | ||||
| public class ObtainTicketApiController { | ||||
| 
 | ||||
|     @GetMapping(value = "/obtainTicket.action", produces = {"application/xml;charset=utf-8"}) | ||||
|     @ResponseBody | ||||
|     public ResponseEntity<String> obtainTicket(LicenseContextHolder.ObtainTicketRequest request) { | ||||
|         return ResponseEntity.ok() | ||||
|                 .contentType(MediaType.APPLICATION_XML) | ||||
|                 .body(LicenseContextHolder.obtainTicket(request)); | ||||
|     } | ||||
| } | ||||
|  | @ -3,12 +3,10 @@ package com.jetbrains.help.util; | |||
| import cn.hutool.core.io.FileUtil; | ||||
| import cn.hutool.core.text.CharSequenceUtil; | ||||
| import cn.hutool.core.util.ObjectUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import org.springframework.boot.system.ApplicationHome; | ||||
| import org.springframework.core.io.ClassPathResource; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| public interface FileTools { | ||||
| 
 | ||||
|  | @ -19,6 +17,10 @@ public interface FileTools { | |||
|         return getFile(path).exists(); | ||||
|     } | ||||
| 
 | ||||
|     static boolean fileNotExists(String path) { | ||||
|         return !fileExists(path); | ||||
|     } | ||||
| 
 | ||||
|     static File getFile(String path) { | ||||
|         File homeDir = application.getDir(); | ||||
|         File source = application.getSource(); | ||||
|  |  | |||
|  | @ -6,6 +6,6 @@ spring: | |||
| server: | ||||
|   port: 10768 | ||||
| help: | ||||
|   default-license-name: 光云 | ||||
|   default-assignee-name: 藏柏 | ||||
|   default-expiry-date: 2111-11-11 | ||||
|   default-license-name: cikaros.top | ||||
|   default-assignee-name: Cikaros | ||||
|   default-expiry-date: 2099-12-31 | ||||
							
								
								
									
										31
									
								
								src/main/resources/external/certificate/license-root.key
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/main/resources/external/certificate/license-root.key
									
									
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| -----BEGIN CERTIFICATE----- | ||||
| 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 | ||||
| 7tlDFnvaRnQukqSG+VqNWg== | ||||
| -----END CERTIFICATE----- | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Cikaros
						Cikaros