server
This commit is contained in:
parent
6f6e0b0cd4
commit
77be634933
|
@ -41,9 +41,5 @@
|
||||||
<source>${project.parent.basedir}/jetbra-agent/target/jetbra-agent.jar</source>
|
<source>${project.parent.basedir}/jetbra-agent/target/jetbra-agent.jar</source>
|
||||||
<destName>jetbra-agent.jar</destName>
|
<destName>jetbra-agent.jar</destName>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<source>${project.parent.basedir}/readme.md</source>
|
|
||||||
<destName>readme.md</destName>
|
|
||||||
</file>
|
|
||||||
</files>
|
</files>
|
||||||
</assembly>
|
</assembly>
|
||||||
|
|
|
@ -27,12 +27,31 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcpkix-jdk18on</artifactId>
|
||||||
|
<version>1.72</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk18on</artifactId>
|
||||||
|
<version>1.72</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -40,8 +59,17 @@
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,92 @@
|
||||||
|
package win.novice.li.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.bouncycastle.openssl.PEMKeyPair;
|
||||||
|
import org.bouncycastle.openssl.PEMParser;
|
||||||
|
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import win.novice.li.model.License;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class LicenseController {
|
||||||
|
private static final PrivateKey PRIVATE_KEY = getPrivateKey();
|
||||||
|
private static final X509Certificate CRT = getCertificate();
|
||||||
|
|
||||||
|
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
|
@PostMapping("/generateLicense")
|
||||||
|
@SneakyThrows
|
||||||
|
public Map<String, Object> generateLicense(@RequestBody @Validated License license) {
|
||||||
|
Map<String, Object> ans = new HashMap<>();
|
||||||
|
|
||||||
|
String licenseId = generateLicenseId();
|
||||||
|
license.setLicenseId(licenseId);
|
||||||
|
|
||||||
|
String licensePart = MAPPER.writeValueAsString(license);
|
||||||
|
byte[] licensePartBytes = licensePart.getBytes(StandardCharsets.UTF_8);
|
||||||
|
String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);
|
||||||
|
|
||||||
|
|
||||||
|
Signature signature = Signature.getInstance("SHA1withRSA");
|
||||||
|
signature.initSign(PRIVATE_KEY);
|
||||||
|
signature.update(licensePartBytes);
|
||||||
|
byte[] signatureBytes = signature.sign();
|
||||||
|
String sigResultsBase64 = Base64.getEncoder().encodeToString(signatureBytes);
|
||||||
|
|
||||||
|
String result = licenseId + "-" + licensePartBase64 + "-" + sigResultsBase64 + "-" + Base64.getEncoder().encodeToString(CRT.getEncoded());
|
||||||
|
|
||||||
|
ans.put("license",result);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
|
public static String generateLicenseId() {
|
||||||
|
int licenseLength = 10;
|
||||||
|
StringBuilder sb = new StringBuilder(licenseLength);
|
||||||
|
for (int i = 0; i < licenseLength; i++) {
|
||||||
|
int randomIndex = random.nextInt(ALLOWED_CHARACTERS.length());
|
||||||
|
char randomChar = ALLOWED_CHARACTERS.charAt(randomIndex);
|
||||||
|
sb.append(randomChar);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
static PrivateKey getPrivateKey() {
|
||||||
|
ClassPathResource licenseKeyResource = new ClassPathResource("jetbra.key");
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
PEMParser pemParser = new PEMParser(new InputStreamReader(licenseKeyResource.getInputStream()));
|
||||||
|
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
|
||||||
|
Object object = pemParser.readObject();
|
||||||
|
KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
|
||||||
|
return kp.getPrivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
static X509Certificate getCertificate() {
|
||||||
|
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||||
|
ClassPathResource crtResource = new ClassPathResource("jetbra.crt");
|
||||||
|
return (X509Certificate) certificateFactory.generateCertificate(crtResource.getInputStream());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package win.novice.li.model;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class License {
|
||||||
|
private String licenseId;
|
||||||
|
@NotBlank
|
||||||
|
private String licenseeName = "Test";
|
||||||
|
@NotBlank
|
||||||
|
private String assigneeName = "novice.li";
|
||||||
|
@NotNull
|
||||||
|
private String assigneeEmail = "";
|
||||||
|
@NotNull
|
||||||
|
private String licenseRestriction = "";
|
||||||
|
@NotNull
|
||||||
|
private Boolean checkConcurrentUse = false;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
private List<@Valid Product> products;
|
||||||
|
@NotBlank
|
||||||
|
private String metadata = "0120230102PPAA013009";
|
||||||
|
@NotBlank
|
||||||
|
private String hash = "41472961/0:1563609451";
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Min(1)
|
||||||
|
private Integer gracePeriodDays = 7;
|
||||||
|
@NotNull
|
||||||
|
private Boolean autoProlongated = true;
|
||||||
|
@NotNull
|
||||||
|
private Boolean isAutoProlongated = true;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
package win.novice.li.model;
|
||||||
|
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Product {
|
||||||
|
@NotBlank
|
||||||
|
private String code;
|
||||||
|
@NotBlank
|
||||||
|
private String fallbackDate = "2025-12-31";
|
||||||
|
@NotBlank
|
||||||
|
private String paidUpTo = "2025-12-31";
|
||||||
|
@NotNull
|
||||||
|
private Boolean extended = false;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEtTCCAp2gAwIBAgIUDyuccmylba71lZQAQic5TJiAhwwwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwGDEWMBQGA1UEAwwNSmV0UHJvZmlsZSBDQTAeFw0yMzA5MjkxNDA2MTJaFw0z
|
||||||
|
MzA5MjcxNDA2MTJaMBExDzANBgNVBAMMBk5vdmljZTCCAiIwDQYJKoZIhvcNAQEB
|
||||||
|
BQADggIPADCCAgoCggIBALenqcGP2ZxGkYqmKA9c4Hzf8+YD1smvmOxKjd+bmTLr
|
||||||
|
utM/hXv1cj1rW3/lqyDtdDk7K6W8/TDq1CRrEt+Do6l30DxhAiC34aH8DmGwgq77
|
||||||
|
xEoLimvH5LpePxflF+tbB1RZtFgFDOIYLdSQaKFH2JDgVKxhLiV3S6jniPhkCtWW
|
||||||
|
rTs+E6vq4N15Bm3NnM5AJILqjtUbOjNfaxVq6RrOoTc0R3Fqqo6yvxo/+JYa2UnH
|
||||||
|
IC+r2dbKuDLMUrtgnydEUdJNX0zH9FtcdELvr48uc9mY038TWUsZUK1pnQbxA2bP
|
||||||
|
yA4qnYJ9IvUgO6LtLXvGFm137YQMS1N41AHDBOrwoNI8UoDX+qI3rM96biFOFvn7
|
||||||
|
Edky7rByzybt3H+zxdojfjvpL1E0NO98BT9zfufHAaAxZtlmDOu5LDJe3CGurnyR
|
||||||
|
MRExbtc+Qjl1mUh6tG4lakAwdsoxry0GdG72yaYyb9it53kaFks/T/s7Z7bRJzVF
|
||||||
|
zQDV1Y4bzUtk43vKm2vztBVlQkBkZY5f2Jbe5Ig3b8swQzBnOT0mrL5SPUhwmQ6I
|
||||||
|
xkEWztj55OEujBMmRr92oESuq9ZYMaeLidKWVR3/++HA8BRZaRGEKtSHZCbFEFdi
|
||||||
|
hDxxJv9Xh6NuT/ewJ6HYp+0NQpFnUnJ72n8wV+tudpam7aKcdzVmz7cNwOhG2Ls7
|
||||||
|
AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAIdeaQfKni7tXtcywC3zJvGzaaj242pS
|
||||||
|
WB1y40HW8jub0uHjTLsBPX27iA/5rb+rNXtUWX/f2K+DU4IgaIiiHhkDrMsw7piv
|
||||||
|
azqwA9h7/uA0A5nepmTYf/HY4W6P2stbeqInNsFRZXS7Jg4Q5LgEtHKo/H8USjtV
|
||||||
|
w9apmE3BCElkXRuelXMsSllpR/JEVv/8NPLmnHSY02q4KMVW2ozXtaAxSYQmZswy
|
||||||
|
P1YnBcnRukoI4igobpcKQXwGoQCIUlec8LbFXYM9V2eNCwgABqd4r67m7QJq31Y/
|
||||||
|
1TJysQdMH+hoPFy9rqNCxSq3ptpuzcYAk6qVf58PrrYH/6bHwiYPAayvvdzNPOhM
|
||||||
|
9OCwomfcazhK3y7HyS8aBLntTQYFf7vYzZxPMDybYTvJM+ClCNnVD7Q9fttIJ6eM
|
||||||
|
XFsXb8YK1uGNjQW8Y4WHk1MCHuD9ZumWu/CtAhBn6tllTQWwNMaPOQvKf1kr1Kt5
|
||||||
|
etrONY+B6O+Oi75SZbDuGz7PIF9nMPy4WB/8XgKdVFtKJ7/zLIPHgY8IKgbx/VTz
|
||||||
|
6uBhYo8wOf3xzzweMnn06UcfV3JGNvtMuV4vlkZNNxXeifsgzHugCvJX0nybhfBh
|
||||||
|
fIqVyfK6t0eKJqrvp54XFEtJGR+lf3pBfTdcOI6QFEPKGZKoQz8Ck+BC/WBDtbjc
|
||||||
|
/uYKczZ8DKZu
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -1,3 +0,0 @@
|
||||||
<html>
|
|
||||||
<p>hello world</p>
|
|
||||||
</html>
|
|
Loading…
Reference in New Issue