本项目只探讨Jrebel激活授权服务器的实现原理,请勿用于非法用途,产生一切后果与本人无关
源码文末自领!
JRebel许可证激活服务器是一个用于激活JRebel开发工具的服务器应用。本文基于Java Spring Boot实现,详细分析了从客户端发起请求到服务器响应的完整激活流程,包括参数解析、签名验证、响应生成等关键技术节点。
系统架构
框架: Spring Boot 3.2.0
语言: Java 17
构建工具: Maven
Web服务器: 内嵌Tomcat
加密算法: RSA + SHA1/MD5
核心组件
JRebelController: 请求控制器,处理HTTP请求
LicenseService: 许可证服务,处理业务逻辑
CryptoUtil: 加密工具,处理RSA签名
UuidUtil: UUID生成工具
ServerConfig: 服务器配置
激活流程详解
客户端(JRebel IDE)向服务器发送POST请求,目标地址为:
POST /jrebel/leases
Content-Type: application/x-www-form-urlencoded
请求参数:
product=ExStudios
randomness=3u0N0yIl%2F6Y%3D
clientTime=1752200923427
definedUserId=745221877%40qq.com
token=669d1071-6027-4d4d-afb9-9a4980239408
oldGuid=R21xWFaL5act6ymdG4kajg1x%2BUlEcH6LboX%2FpvGnCxs%3D
guid=R21xWFaL5act6ymdG4kajg1x%2BUlEcH6LboX%2FpvGnCxs%3D
username=ExStudios
请求处理入口
@PostMapping(value = {"/jrebel/leases", "/agent/leases"},
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<JRebelLeasesStruct> jrebelLeases(@RequestBody String body,
HttpServletRequest request) {
logRequest(request, body);
try {
Map<String, String> parameters = parseParameters(body);
// 验证必需参数
if (!validateRequiredParameters(parameters, "randomness", "username", "guid")) {
return ResponseEntity.status(403).build();
}
JRebelLeasesStruct response = licenseService.createLeaseResponse(parameters);
return ResponseEntity.ok(response);
} catch (Exception e) {
logger.error("Error processing jrebel leases request", e);
return ResponseEntity.status(403).build();
}
}
步骤解析
日志记录: 记录请求方法和客户端信息
参数解析: 将URL编码的表单数据解析为Map
参数验证: 验证必需参数(randomness、username、guid)
业务处理: 调用LicenseService处理业务逻辑
响应返回: 返回JSON格式的许可证信息
参数解析机制
private Map<String, String> parseParameters(String body) {
Map<String, String> parameters = new HashMap<>();
if (body != null && !body.isEmpty()) {
String[] pairs = body.split("&");
for (String pair : pairs) {
String[] keyValue = pair.split("=", 2);
if (keyValue.length == 2) {
try {
String key = java.net.URLDecoder.decode(keyValue[0], "UTF-8");
String value = java.net.URLDecoder.decode(keyValue[1], "UTF-8");
parameters.put(key, value);
} catch (Exception e) {
// 如果解码失败,使用原始值
parameters.put(keyValue[0], keyValue[1]);
}
}
}
}
return parameters;
}
解析逻辑:
按&分割参数对
按=分割键值对
URL解码处理特殊字符
异常处理确保解析稳定性
业务逻辑处理
public JRebelLeasesStruct createLeaseResponse(Map<String, String> parameters) throws Exception {
String clientRandomness = parameters.get("randomness");
String username = parameters.get("username");
String guid = parameters.get("guid");
String product = parameters.get("product");
String clientTime = parameters.get("clientTime");
String offlineDays = parameters.get("offlineDays");
String oldGuid = parameters.get("oldGuid");
String offlineParam = parameters.get("offline");
// 打印调试信息
System.out.println("=== JRebel客户端请求参数 ===");
System.out.println("product = " + product);
System.out.println("randomness = " + clientRandomness);
// ... 其他参数打印
}
核心签名算法
生成规则:
11位随机字符(字母+数字)
末尾添加=符号
示例:H2ulzLlh7E0=
private String generateServerRandomness() {
String charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 11; i++) {
int index = (int) (Math.random() * charset.length());
sb.append(charset.charAt(index));
}
return sb.toString() + "=";
}
签名字符串格式:
在线模式: clientRandomness;serverRandomness;guid;false
离线模式: clientRandomness;serverRandomness;guid;true;validFrom;validUntil
test123;H2ulzLlh7E0=;test-guid;false
private String createLeaseSignature(String clientRandomness, String serverRandomness,
String guid, boolean offline, String validFrom, String validUntil) throws Exception {
String s2;
if (offline) {
s2 = clientRandomness + ";" + serverRandomness + ";" + guid + ";" + String.valueOf(offline) + ";" + validFrom + ";" + validUntil;
} else {
s2 = clientRandomness + ";" + serverRandomness + ";" + guid + ";" + String.valueOf(offline);
}
System.out.println("签名拼接字符串: " + s2);
byte[] signature = cryptoUtil.signWithSha1(s2.getBytes());
String base64 = cryptoUtil.encodeBase64(signature);
return base64;
}
public byte[] signWithSha1(byte[] data) throws Exception {
PrivateKey privateKey = getPrivateKey(PRIVATE_KEY);
// 使用标准的SHA1withRSA方法
Signature signature = Signature.getInstance("SHA1withRSA");
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public class JRebelLeasesStruct {
@JsonProperty("serverVersion")
private String serverVersion = "3.2.4";
@JsonProperty("serverProtocolVersion")
private String serverProtocolVersion = "1.1";
@JsonProperty("serverGuid")
private String serverGuid = "a1b4aea8-b031-4302-b602-670a990272cb";
@JsonProperty("signature")
private String signature;
@JsonProperty("serverRandomness")
private String serverRandomness;
@JsonProperty("company")
private String company;
// ... 其他字段
}
完整示例:
{
"serverVersion": "3.2.4",
"serverProtocolVersion": "1.1",
"serverGuid": "a1b4aea8-b031-4302-b602-670a990272cb",
"groupType": "managed",
"id": 1,
"licenseType": 1,
"evaluationLicense": false,
"signature": "YBMQXy7UUkAwZALPksIIybibzpWl73bueDDVPguc1NM3OOfUl8GmVjGrP+b6ZrMJwLD8QMn2KOeyMD/p9UW/7jQnIzsrJflm2WZsyVN6RFeGK7FcxldMxRdUQu3RBazbW714DkBahxFMYnHzJ3lZie0JLERN39osLJU04q0/Rlg=",
"serverRandomness": "4Euox6RDQrf=",
"seatPoolType": "standalone",
"statusCode": "SUCCESS",
"offline": false,
"validFrom": null,
"validUntil": null,
"company": "test@example.com",
"orderId": "",
"zeroIds": [],
"licenseValidFrom": 1490544001000,
"licenseValidUntil": 1891839999000
}
代码已开源至技术公众号 : Exstudios
回复Jrebel 领取
评论前必须登录!
注册