feat:授权码SDK版本迭代,新增设备机器码校验
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>nl-verify-check-sdk</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.nl.api;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.nl.core.LicenseResult;
|
||||
import org.nl.core.LicenseVerifier;
|
||||
import org.nl.util.MachineCodeUtil;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -32,4 +33,10 @@ public class LicenseController {
|
||||
}
|
||||
return new ResponseEntity<>(verify, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping("/machine-code")
|
||||
public ResponseEntity<Object> getMachineCode() {
|
||||
String machineCode = MachineCodeUtil.getMachineCode();
|
||||
return new ResponseEntity<>(machineCode, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,8 @@ public class LicenseAutoConfiguration implements WebMvcConfigurer {
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authInterceptor)
|
||||
.addPathPatterns("/**")
|
||||
.excludePathPatterns("/auth/login", "/auth/code", "/auth/logout", "/auth/info", "/api/verify/activity");
|
||||
.excludePathPatterns("/auth/login", "/auth/code", "/auth/logout", "/auth/info",
|
||||
"/api/verify/activity", "/api/verify/machine-code");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,14 @@ public class LicenseResult {
|
||||
private String message;
|
||||
/** 证书 key */
|
||||
private String content;
|
||||
/** 机器码 */
|
||||
private String machineCode;
|
||||
public static LicenseResult requestResult(Boolean result, String message, String content) {
|
||||
return LicenseResult.builder()
|
||||
.message(message)
|
||||
.result(result)
|
||||
.content(content)
|
||||
.machineCode(null)
|
||||
.build();
|
||||
}
|
||||
public static LicenseResult requestOk(String message, String content) {
|
||||
@@ -28,6 +31,7 @@ public class LicenseResult {
|
||||
.message(message)
|
||||
.result(true)
|
||||
.content(content)
|
||||
.machineCode(null)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.nl.core;
|
||||
|
||||
import org.nl.util.MachineCodeUtil;
|
||||
import org.nl.util.RSAUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -33,7 +34,18 @@ public class LicenseVerifier {
|
||||
return LicenseResult.requestResult(false, "请输入授权码", null);
|
||||
}
|
||||
try {
|
||||
String expirationStr = rsaUtil.decrypt(authCode);
|
||||
String decrypted = rsaUtil.decrypt(authCode);
|
||||
String[] parts = decrypted.split("\\|");
|
||||
String expirationStr = parts[0];
|
||||
String machineFingerprint = parts.length > 1 ? parts[1] : null;
|
||||
|
||||
if (machineFingerprint != null && !machineFingerprint.isEmpty()) {
|
||||
String currentMachineCode = MachineCodeUtil.getMachineCode();
|
||||
if (!currentMachineCode.equals(machineFingerprint)) {
|
||||
return LicenseResult.requestResult(false, "授权码与当前机器不匹配", authCode);
|
||||
}
|
||||
}
|
||||
|
||||
if ("-1".equals(expirationStr)) {
|
||||
return LicenseResult.requestOk("永久授权", authCode);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.nl.util;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 机器指纹工具类,基于 MAC 地址 + 主机名生成唯一机器标识。
|
||||
* @Author: zhaoyf
|
||||
* @Date: 2026/5/25
|
||||
*/
|
||||
public class MachineCodeUtil {
|
||||
|
||||
private static volatile String cachedMachineCode;
|
||||
|
||||
public static String getMachineCode() {
|
||||
if (cachedMachineCode != null) {
|
||||
return cachedMachineCode;
|
||||
}
|
||||
synchronized (MachineCodeUtil.class) {
|
||||
if (cachedMachineCode != null) {
|
||||
return cachedMachineCode;
|
||||
}
|
||||
try {
|
||||
|
||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
List<String> macs = new ArrayList<>();
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface ni = interfaces.nextElement();
|
||||
if (ni.isLoopback() || ni.isVirtual() || !ni.isUp()) {
|
||||
continue;
|
||||
}
|
||||
byte[] mac = ni.getHardwareAddress();
|
||||
if (mac != null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : mac) {
|
||||
sb.append(String.format("%02X", b));
|
||||
}
|
||||
macs.add(sb.toString());
|
||||
}
|
||||
}
|
||||
Collections.sort(macs);
|
||||
|
||||
String combined = String.join("|", macs);
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||
byte[] hash = md.digest(combined.getBytes("UTF-8"));
|
||||
|
||||
StringBuilder hex = new StringBuilder();
|
||||
for (byte b : hash) {
|
||||
hex.append(String.format("%02x", b));
|
||||
}
|
||||
cachedMachineCode = hex.toString();
|
||||
} catch (Exception e) {
|
||||
cachedMachineCode = "UNKNOWN";
|
||||
}
|
||||
return cachedMachineCode;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,8 +21,41 @@
|
||||
<dependency>
|
||||
<groupId>org.nl</groupId>
|
||||
<artifactId>nl-verify-check-sdk</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.gitee.lcm742320521</groupId>
|
||||
<artifactId>classfinal-maven-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<configuration>
|
||||
<!-- 必填:加密密码,请务必修改为强密码并妥善保管 -->
|
||||
<password>nl2024</password>
|
||||
<!-- 需要加密的包名(支持多个,逗号分隔) -->
|
||||
<packages>org.nl</packages>
|
||||
<!-- 需要加密的配置文件 -->
|
||||
<cfgfiles>application.yml,application-dev.yml,application-prod.yml</cfgfiles>
|
||||
<!-- 排除不需要加密的包(如实体类、DTO) -->
|
||||
<excludes>org.nl.**.domain.**,org.nl.Application</excludes>
|
||||
<!-- 可选:绑定机器码,使加密后的jar只能在此机器运行 -->
|
||||
<!-- <code>目标机器的唯一标识码</code> -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>classFinal</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1 +1 @@
|
||||
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
|
||||
Reference in New Issue
Block a user