├── .gitignore ├── Dockerfile ├── README.md ├── docs ├── mini-program.jpg ├── usage.png └── wechat.jpg ├── index.png ├── pom.xml └── src └── main ├── java └── com │ └── imjcker │ └── jrebel │ ├── JrebelApplication.java │ ├── config │ ├── CommonConfig.java │ └── JrebelConfigurationProperties.java │ ├── controller │ └── JrebelController.java │ ├── exception │ └── GlobalExceptionHandler.java │ └── sys │ ├── Base64.java │ ├── ByteUtil.java │ ├── Hex.java │ ├── HttpClientUtils.java │ ├── IpUtils.java │ ├── JrebelSign.java │ ├── LicenseServer2ToJRebelPrivateKey.java │ └── rsasign.java └── resources ├── META-INF └── spring-configuration-metadata.json ├── application.yml ├── banner.txt ├── favicon.ico ├── rebel.xml ├── static ├── favicon.ico ├── mini-program.jpg └── wechat.jpg └── templates └── index.ftl /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | logs 33 | 34 | rebel.xml -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:11 2 | ARG JAR_FILE 3 | ADD target/${JAR_FILE} /app.jar 4 | ENV JAVA_OPTS="-Xmx512m -Xms512m" 5 | EXPOSE 9090 6 | ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "${JAVA_OPTS}", "-jar", "-Duser.timezone=GMT+8", "/app.jar"] 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jrebel License Server 2 | 3 | 一个基于spring boot的jrebel激活服务。 4 | 5 | > A spring boot based Jrebel License Server. 6 | 7 | docker官方镜像地址[点这里](https://hub.docker.com/repository/docker/imjcker/jrebel-license-server) 8 | 9 | > docker image available [here](https://hub.docker.com/repository/docker/imjcker/jrebel-license-server) 10 | 11 | 12 | 13 | ![usage](/index.png) 14 | ## Usage (自建教程) 15 | 16 | 17 | ```shell script 18 | java -jar jrebel-license-server-2.0.0.jar 19 | 20 | # run daemond 21 | 22 | nohup java -jar jrebel-license-server-2.0.0.jar >/dev/null 2>&1 & 23 | 24 | # for docker users 25 | 26 | sudo docker run -d --name jrebel-license-server -p 9090:9090 --restart always imjcker/jrebel-license-server:latest 27 | 28 | ``` 29 | 30 | [license]: https://www.apache.org/licenses/LICENSE-2.0 31 | 32 | -------------------------------------------------------------------------------- /docs/mini-program.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/docs/mini-program.jpg -------------------------------------------------------------------------------- /docs/usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/docs/usage.png -------------------------------------------------------------------------------- /docs/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/docs/wechat.jpg -------------------------------------------------------------------------------- /index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/index.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.7.9 9 | 10 | 11 | com.imjcker 12 | jrebel-license-server 13 | 2.0.0 14 | jrebel-license-server 15 | jrebel 16 | 17 | 18 | 1.8 19 | 2.7.9 20 | 2021.0.6 21 | 192.168.0.115:5000 22 | 23 | ${env.DOCKER_REMOTE_HOST} 24 | 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-freemarker 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-configuration-processor 38 | true 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-devtools 43 | runtime 44 | true 45 | 46 | 47 | 48 | org.apache.httpcomponents 49 | httpclient 50 | 4.5.13 51 | 52 | 53 | com.alibaba 54 | fastjson 55 | 1.2.83 56 | 57 | 58 | org.projectlombok 59 | lombok 60 | true 61 | 62 | 63 | 64 | org.bouncycastle 65 | bcprov-jdk15on 66 | 1.69 67 | 68 | 69 | 70 | commons-codec 71 | commons-codec 72 | 1.13 73 | 74 | 75 | 76 | com.alibaba.fastjson2 77 | fastjson2 78 | 2.0.39 79 | 80 | 81 | 87 | 88 | 89 | org.apache.commons 90 | commons-lang3 91 | 3.1 92 | 93 | 94 | 95 | org.webjars 96 | bootstrap 97 | 4.5.0 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | org.springframework.boot 106 | spring-boot-maven-plugin 107 | 108 | 109 | com.spotify 110 | docker-maven-plugin 111 | 1.2.2 112 | 113 | 114 | 115 | build-image 116 | package 117 | 118 | build 119 | push 120 | 121 | 122 | 123 | 124 | 125 | ${docker.remote.host} 126 | ${docker.image.registryUrl} 127 | 128 | 129 | ${docker.image.registryUrl}/${project.groupId}/${project.artifactId}:latest 130 | 131 | 132 | ${project.version} 133 | 134 | 135 | 136 | 137 | openjdk:8-jdk-alpine 138 | /root/ 139 | ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "-Duser.timezone=GMT+8", "${project.build.finalName}.jar"] 140 | 141 | 142 | 143 | 144 | ${project.build.directory} 145 | 146 | ${project.build.finalName}.jar 147 | 148 | /root/ 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/JrebelApplication.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.scheduling.annotation.EnableScheduling; 10 | 11 | import java.util.UUID; 12 | 13 | @EnableScheduling 14 | @SpringBootApplication 15 | public class JrebelApplication implements CommandLineRunner { 16 | private static final Logger log = LoggerFactory.getLogger(JrebelApplication.class); 17 | @Value("${server.port}") 18 | private String port; 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(JrebelApplication.class, args); 22 | } 23 | 24 | @Override 25 | public void run(String... args) { 26 | log.info("License Server started at http://localhost:" + port); 27 | log.info("JetBrains Activation address is: http://localhost:" + port + "/"); 28 | log.info("JRebel 7.1 and earlier version Activation address is: http://localhost:" + port + "/{tokenname}, with any email."); 29 | log.info("JRebel 2018.1 and later version Activation address is: http://localhost:" + port + "/{guid}(eg:http://localhost:" + port + "/" + UUID.randomUUID().toString() + "), with any email."); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/config/CommonConfig.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.config; 2 | 3 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @EnableConfigurationProperties(JrebelConfigurationProperties.class) 8 | public class CommonConfig { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/config/JrebelConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 自定义配置 9 | */ 10 | @ConfigurationProperties(prefix = "jrebel") 11 | public class JrebelConfigurationProperties { 12 | 13 | /** 14 | * 获取jrebel部署服务器的公网IP地址 15 | */ 16 | @Deprecated 17 | private String ipFetchUrl; 18 | /** 19 | * jrebel active addr for China 20 | */ 21 | private String urlCn; 22 | /** 23 | * jrebel active addr for global 24 | */ 25 | private String urlGlobal; 26 | /** 27 | * social networks url list 28 | */ 29 | private List social; 30 | 31 | @Deprecated 32 | public String getIpFetchUrl() { 33 | return ipFetchUrl; 34 | } 35 | 36 | @Deprecated 37 | public void setIpFetchUrl(String ipFetchUrl) { 38 | this.ipFetchUrl = ipFetchUrl; 39 | } 40 | 41 | public String getUrlCn() { 42 | return urlCn; 43 | } 44 | 45 | public void setUrlCn(String urlCn) { 46 | this.urlCn = urlCn; 47 | } 48 | 49 | public String getUrlGlobal() { 50 | return urlGlobal; 51 | } 52 | 53 | public void setUrlGlobal(String urlGlobal) { 54 | this.urlGlobal = urlGlobal; 55 | } 56 | 57 | public List getSocial() { 58 | return social; 59 | } 60 | 61 | public void setSocial(List social) { 62 | this.social = social; 63 | } 64 | 65 | public static class Social{ 66 | private String name; 67 | private String url; 68 | 69 | public String getName() { 70 | return name; 71 | } 72 | 73 | public void setName(String name) { 74 | this.name = name; 75 | } 76 | 77 | public String getUrl() { 78 | return url; 79 | } 80 | 81 | public void setUrl(String url) { 82 | this.url = url; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/controller/JrebelController.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.controller; 2 | 3 | import com.alibaba.fastjson2.JSONObject; 4 | import com.imjcker.jrebel.config.JrebelConfigurationProperties; 5 | import com.imjcker.jrebel.sys.JrebelSign; 6 | import com.imjcker.jrebel.sys.rsasign; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.ModelMap; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.io.IOException; 15 | import java.text.SimpleDateFormat; 16 | import java.util.Date; 17 | import java.util.Locale; 18 | import java.util.UUID; 19 | 20 | @Controller 21 | public class JrebelController { 22 | private final JrebelConfigurationProperties jrebel; 23 | 24 | @Autowired 25 | public JrebelController(JrebelConfigurationProperties jrebel) { 26 | this.jrebel = jrebel; 27 | } 28 | 29 | @RequestMapping("/") 30 | public String indexHandler(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws IOException { 31 | response.setContentType("text/html; charset=utf-8"); 32 | response.setStatus(HttpServletResponse.SC_OK); 33 | int port = request.getServerPort(); 34 | model.addAttribute("port", Integer.toString(port)); 35 | model.addAttribute("uuid", UUID.randomUUID().toString()); 36 | model.addAttribute("jrebel", jrebel); 37 | 38 | return "index"; 39 | } 40 | 41 | @RequestMapping("/jrebel/validate-connection") 42 | public void jrebelValidateHandler(HttpServletRequest request, HttpServletResponse response) throws IOException { 43 | response.setContentType("application/json; charset=utf-8"); 44 | response.setStatus(HttpServletResponse.SC_OK); 45 | String jsonStr = "{\n" + 46 | " \"serverVersion\": \"3.2.4\",\n" + 47 | " \"serverProtocolVersion\": \"1.1\",\n" + 48 | " \"serverGuid\": \"a1b4aea8-b031-4302-b602-670a990272cb\",\n" + 49 | " \"groupType\": \"managed\",\n" + 50 | " \"statusCode\": \"SUCCESS\",\n" + 51 | " \"company\": \"Administrator\",\n" + 52 | " \"canGetLease\": true,\n" + 53 | " \"licenseType\": 1,\n" + 54 | " \"evaluationLicense\": false,\n" + 55 | " \"seatPoolType\": \"standalone\"\n" + 56 | "}\n"; 57 | JSONObject jsonObject = JSONObject.parseObject(jsonStr); 58 | String body = jsonObject.toString(); 59 | response.getWriter().print(body); 60 | } 61 | 62 | @RequestMapping({"/jrebel/leases/1", "/agent/leases/1"}) 63 | public void jrebelLeases1Handler(HttpServletRequest request, HttpServletResponse response) throws IOException { 64 | response.setContentType("application/json; charset=utf-8"); 65 | response.setStatus(HttpServletResponse.SC_OK); 66 | String username = request.getParameter("username"); 67 | String jsonStr = "{\n" + 68 | " \"serverVersion\": \"3.2.4\",\n" + 69 | " \"serverProtocolVersion\": \"1.1\",\n" + 70 | " \"serverGuid\": \"a1b4aea8-b031-4302-b602-670a990272cb\",\n" + 71 | " \"groupType\": \"managed\",\n" + 72 | " \"statusCode\": \"SUCCESS\",\n" + 73 | " \"msg\": null,\n" + 74 | " \"statusMessage\": null\n" + 75 | "}\n"; 76 | JSONObject jsonObject = JSONObject.parseObject(jsonStr); 77 | if (username != null) { 78 | jsonObject.put("company", username); 79 | } 80 | String body = jsonObject.toString(); 81 | response.getWriter().print(body); 82 | 83 | } 84 | 85 | @RequestMapping({"/jrebel/leases", "/agent/leases"}) 86 | public void jrebelLeasesHandler(HttpServletRequest request, HttpServletResponse response) throws IOException { 87 | response.setContentType("application/json; charset=utf-8"); 88 | response.setStatus(HttpServletResponse.SC_OK); 89 | String clientRandomness = request.getParameter("randomness"); 90 | String username = request.getParameter("username"); 91 | String guid = request.getParameter("guid"); 92 | System.out.println(request.getParameterNames()); 93 | boolean offline = Boolean.parseBoolean(request.getParameter("offline")); 94 | String validFrom = "null"; 95 | String validUntil = "null"; 96 | if (offline) { 97 | String clientTime = request.getParameter("clientTime"); 98 | String offlineDays = request.getParameter("offlineDays"); 99 | long clinetTimeUntil = Long.parseLong(clientTime) + 180L * 24 * 60 * 60 * 1000; 100 | validFrom = clientTime; 101 | validUntil = String.valueOf(clinetTimeUntil); 102 | } 103 | String jsonStr = "{\n" + 104 | " \"serverVersion\": \"3.2.4\",\n" + 105 | " \"serverProtocolVersion\": \"1.1\",\n" + 106 | " \"serverGuid\": \"a1b4aea8-b031-4302-b602-670a990272cb\",\n" + 107 | " \"groupType\": \"managed\",\n" + 108 | " \"id\": 1,\n" + 109 | " \"licenseType\": 1,\n" + 110 | " \"evaluationLicense\": false,\n" + 111 | " \"signature\": \"OJE9wGg2xncSb+VgnYT+9HGCFaLOk28tneMFhCbpVMKoC/Iq4LuaDKPirBjG4o394/UjCDGgTBpIrzcXNPdVxVr8PnQzpy7ZSToGO8wv/KIWZT9/ba7bDbA8/RZ4B37YkCeXhjaixpmoyz/CIZMnei4q7oWR7DYUOlOcEWDQhiY=\",\n" + 112 | " \"serverRandomness\": \"H2ulzLlh7E0=\",\n" + 113 | " \"seatPoolType\": \"standalone\",\n" + 114 | " \"statusCode\": \"SUCCESS\",\n" + 115 | " \"offline\": " + String.valueOf(offline) + ",\n" + 116 | " \"validFrom\": " + validFrom + ",\n" + 117 | " \"validUntil\": " + validUntil + ",\n" + 118 | " \"company\": \"Administrator\",\n" + 119 | " \"orderId\": \"\",\n" + 120 | " \"zeroIds\": [\n" + 121 | " \n" + 122 | " ],\n" + 123 | " \"licenseValidFrom\": 1490544001000,\n" + 124 | " \"licenseValidUntil\": 1691839999000\n" + 125 | "}"; 126 | 127 | JSONObject jsonObject = JSONObject.parseObject(jsonStr); 128 | if (clientRandomness == null || username == null || guid == null) { 129 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 130 | } else { 131 | JrebelSign jrebelSign = new JrebelSign(); 132 | jrebelSign.toLeaseCreateJson(clientRandomness, guid, offline, validFrom, validUntil); 133 | String signature = jrebelSign.getSignature(); 134 | jsonObject.put("signature", signature); 135 | jsonObject.put("company", username); 136 | String body = jsonObject.toString(); 137 | response.getWriter().print(body); 138 | } 139 | } 140 | 141 | @RequestMapping("/rpc/releaseTicket.action") 142 | public void releaseTicketHandler(HttpServletRequest request, HttpServletResponse response) throws IOException { 143 | response.setContentType("text/html; charset=utf-8"); 144 | response.setStatus(HttpServletResponse.SC_OK); 145 | String salt = request.getParameter("salt"); 146 | if (salt == null) { 147 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 148 | } else { 149 | String xmlContent = "OK" + salt + ""; 150 | String xmlSignature = rsasign.Sign(xmlContent); 151 | String body = "\n" + xmlContent; 152 | response.getWriter().print(body); 153 | } 154 | } 155 | 156 | @RequestMapping("/rpc/obtainTicket.action") 157 | public void obtainTicketHandler(HttpServletRequest request, HttpServletResponse response) throws IOException { 158 | response.setContentType("text/html; charset=utf-8"); 159 | response.setStatus(HttpServletResponse.SC_OK); 160 | SimpleDateFormat fm = new SimpleDateFormat("EEE,d MMM yyyy hh:mm:ss Z", Locale.ENGLISH); 161 | String date = fm.format(new Date()) + " GMT"; 162 | //response.setHeader("Date", date); 163 | //response.setHeader("Server", "fasthttp"); 164 | String salt = request.getParameter("salt"); 165 | String username = request.getParameter("userName"); 166 | String prolongationPeriod = "607875500"; 167 | if (salt == null || username == null) { 168 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 169 | } else { 170 | String xmlContent = "" + prolongationPeriod + "OK" + salt + "1licensee=" + username + "\tlicenseType=0\t"; 171 | String xmlSignature = rsasign.Sign(xmlContent); 172 | String body = "\n" + xmlContent; 173 | response.getWriter().print(body); 174 | } 175 | } 176 | 177 | @RequestMapping("/rpc/ping.action") 178 | public void pingHandler(HttpServletRequest request, HttpServletResponse response) throws IOException { 179 | response.setContentType("text/html; charset=utf-8"); 180 | response.setStatus(HttpServletResponse.SC_OK); 181 | String salt = request.getParameter("salt"); 182 | if (salt == null) { 183 | response.setStatus(HttpServletResponse.SC_FORBIDDEN); 184 | } else { 185 | String xmlContent = "OK" + salt + ""; 186 | String xmlSignature = rsasign.Sign(xmlContent); 187 | String body = "\n" + xmlContent; 188 | response.getWriter().print(body); 189 | } 190 | 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/exception/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.exception; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.web.bind.annotation.ControllerAdvice; 7 | import org.springframework.web.bind.annotation.ExceptionHandler; 8 | 9 | @Slf4j 10 | @ControllerAdvice 11 | public class GlobalExceptionHandler { 12 | 13 | // 异常处理方法 14 | @ExceptionHandler(Exception.class) 15 | public ResponseEntity handleException(Exception e) { 16 | // 处理异常 17 | String message = "发生异常:" + e.getMessage(); 18 | log.error(message); 19 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(message); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/Base64.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | 4 | public class Base64 { 5 | /** 6 | * 编码 7 | * 8 | * @param bstr 9 | * @return String 10 | */ 11 | public static String encode(byte[] bstr) { 12 | return org.apache.commons.codec.binary.Base64.encodeBase64String(bstr); 13 | } 14 | 15 | /** 16 | * 解码 17 | * 18 | * @param str 19 | * @return string 20 | */ 21 | public static byte[] decode(String str) { 22 | return org.apache.commons.codec.binary.Base64.decodeBase64(str); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/ByteUtil.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | import org.apache.commons.codec.binary.Base64; 3 | 4 | import java.nio.charset.StandardCharsets; 5 | import java.util.Random; 6 | 7 | public class ByteUtil { 8 | private static final Random a; 9 | 10 | public static String a(final byte[] binaryData) { 11 | if (binaryData == null) { 12 | return null; 13 | } 14 | return new String(Base64.encodeBase64(binaryData), StandardCharsets.UTF_8); 15 | } 16 | 17 | public static byte[] a(final String s) { 18 | if (s == null) { 19 | return null; 20 | } 21 | return Base64.decodeBase64(s.getBytes(StandardCharsets.UTF_8)); 22 | } 23 | 24 | public static byte[] a(final int n) { 25 | final byte[] array = new byte[n]; 26 | ByteUtil.a.nextBytes(array); 27 | return array; 28 | } 29 | 30 | static { 31 | a = new Random(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/Hex.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | public class Hex { 4 | public static String bytesToHexString(byte[] src){ 5 | StringBuilder stringBuilder = new StringBuilder(""); 6 | if (src == null || src.length <= 0) { 7 | return null; 8 | } 9 | for (int i = 0; i < src.length; i++) { 10 | int v = src[i] & 0xFF; 11 | String hv = Integer.toHexString(v); 12 | if (hv.length() < 2) { 13 | stringBuilder.append(0); 14 | } 15 | stringBuilder.append(hv); 16 | } 17 | return stringBuilder.toString(); 18 | } 19 | /** 20 | * Convert hex string to byte[] 21 | * @param hexString the hex string 22 | * @return byte[] 23 | */ 24 | public static byte[] hexStringToBytes(String hexString) { 25 | if (hexString == null || hexString.equals("")) { 26 | return null; 27 | } 28 | hexString = hexString.toUpperCase(); 29 | int length = hexString.length() / 2; 30 | char[] hexChars = hexString.toCharArray(); 31 | byte[] d = new byte[length]; 32 | for (int i = 0; i < length; i++) { 33 | int pos = i * 2; 34 | d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); 35 | } 36 | return d; 37 | } 38 | private static byte charToByte(char c) { 39 | return (byte) "0123456789ABCDEF".indexOf(c); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/HttpClientUtils.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import org.apache.http.HttpEntity; 5 | import org.apache.http.client.config.RequestConfig; 6 | import org.apache.http.client.methods.*; 7 | import org.apache.http.client.utils.URIBuilder; 8 | import org.apache.http.conn.HttpHostConnectException; 9 | import org.apache.http.entity.ByteArrayEntity; 10 | import org.apache.http.entity.ContentType; 11 | import org.apache.http.entity.StringEntity; 12 | import org.apache.http.impl.client.CloseableHttpClient; 13 | import org.apache.http.impl.client.HttpClients; 14 | import org.apache.http.util.EntityUtils; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import java.io.IOException; 19 | import java.net.URI; 20 | import java.nio.charset.StandardCharsets; 21 | import java.util.Map; 22 | import java.util.Set; 23 | 24 | /** 25 | *

Title: HttpClientProxy.java 26 | *

Description: HttpClient请求代理 27 | *

Copyright: Copyright © 2017, CQzlll, All Rights Reserved. 28 | * 29 | * @author CQzlll.zl 30 | * @version 1.0 31 | */ 32 | public class HttpClientUtils { 33 | private static final Logger log = LoggerFactory.getLogger(HttpClientUtils.class); 34 | 35 | public static String postByJson(String uri, Map headers, JSONObject jsonObject) { 36 | StringBuilder loggerMsg = new StringBuilder(); 37 | loggerMsg.append("HttpClientProxy.postByJson(): 调用URI: "); 38 | loggerMsg.append(uri); 39 | loggerMsg.append(headers); 40 | loggerMsg.append(jsonObject); 41 | 42 | HttpPost httpPost = new HttpPost(uri); 43 | 44 | //构造参数数据实体 45 | if (jsonObject != null) { 46 | String transJson = jsonObject.toString(); 47 | HttpEntity httpEntity = new StringEntity(transJson, ContentType.APPLICATION_JSON); 48 | httpPost.setEntity(httpEntity); 49 | } 50 | //构造请求头 51 | if (headers != null && !headers.isEmpty()) { 52 | Set> headerEntrySet = headers.entrySet(); 53 | for (Map.Entry headerEntry : headerEntrySet) { 54 | httpPost.setHeader(headerEntry.getKey(), headerEntry.getValue()); 55 | } 56 | } 57 | String result = null; 58 | try { 59 | result = commonInvoke(httpPost); 60 | loggerMsg.append(result); 61 | log.info(loggerMsg.toString()); 62 | } catch (IOException ex) { 63 | log.error(loggerMsg.toString(), ex); 64 | } 65 | return result; 66 | } 67 | 68 | public static String putByJson(String uri, Map headers, JSONObject jsonObject) { 69 | HttpPut httpPut = new HttpPut(uri); 70 | //构造参数数据实体 71 | if (jsonObject != null) { 72 | String transJson = jsonObject.toString(); 73 | HttpEntity httpEntity = new StringEntity(transJson, ContentType.APPLICATION_JSON); 74 | httpPut.setEntity(httpEntity); 75 | } 76 | //构造请求头 77 | if (headers != null && !headers.isEmpty()) { 78 | Set> headerEntrySet = headers.entrySet(); 79 | for (Map.Entry headerEntry : headerEntrySet) { 80 | httpPut.setHeader(headerEntry.getKey(), headerEntry.getValue()); 81 | } 82 | } 83 | String result = null; 84 | try { 85 | result = commonInvoke(httpPut); 86 | } catch (IOException ex) { 87 | log.error("put by json error: ", ex); 88 | } 89 | return result; 90 | } 91 | 92 | public static String postBytes(String uri, Map headers, byte[] bytes) { 93 | StringBuilder loggerMsg = new StringBuilder(); 94 | loggerMsg.append("HttpClientProxy.postBytes(): 调用URI: "); 95 | loggerMsg.append(uri); 96 | loggerMsg.append(headers); 97 | HttpPost httpPost = new HttpPost(uri); 98 | ByteArrayEntity httpEntity = new ByteArrayEntity(bytes); 99 | httpPost.setEntity(httpEntity); 100 | 101 | //构造请求头 102 | if (headers != null && !headers.isEmpty()) { 103 | Set> headerEntrySet = headers.entrySet(); 104 | for (Map.Entry headerEntry : headerEntrySet) { 105 | httpPost.setHeader(headerEntry.getKey(), headerEntry.getValue()); 106 | } 107 | } 108 | 109 | String result = null; 110 | 111 | try { 112 | result = commonInvoke(httpPost); 113 | loggerMsg.append(result); 114 | log.info(loggerMsg.toString()); 115 | } catch (IOException ex) { 116 | log.error(loggerMsg.toString(), ex); 117 | } 118 | return result; 119 | } 120 | 121 | private static String commonInvoke(HttpEntityEnclosingRequestBase http) throws IOException { 122 | //设置请求和传输超时时间 123 | RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1000 * 1000).setSocketTimeout(3000 * 1000).build(); 124 | http.setConfig(requestConfig); 125 | 126 | CloseableHttpClient httpClient = null; 127 | CloseableHttpResponse httpResponse = null; 128 | 129 | try { 130 | httpClient = HttpClients.createDefault(); 131 | //调用 132 | httpResponse = httpClient.execute(http); 133 | HttpEntity httpEntity = httpResponse.getEntity(); 134 | return EntityUtils.toString(httpEntity); 135 | } catch (IOException ex) { 136 | throw ex; 137 | } finally { 138 | if (httpResponse != null) { 139 | try { 140 | httpResponse.close(); 141 | } catch (IOException ex) { 142 | log.error("关闭HttpResponse失败.", ex); 143 | } 144 | } 145 | if (httpClient != null) { 146 | try { 147 | httpClient.close(); 148 | } catch (IOException ex) { 149 | log.error("关闭HttpClient失败.", ex); 150 | } 151 | } 152 | } 153 | } 154 | 155 | public static String get(String url, Map headers, Map params) { 156 | StringBuilder loggerMsg = new StringBuilder(); 157 | // 创建Httpclient对象 158 | CloseableHttpClient httpclient = HttpClients.createDefault(); 159 | String resultString = ""; 160 | CloseableHttpResponse response = null; 161 | try { 162 | // 创建uri 163 | URIBuilder builder = new URIBuilder(url); 164 | if (params != null) { 165 | for (String key : params.keySet()) { 166 | builder.addParameter(key, params.get(key)); 167 | } 168 | } 169 | URI uri = builder.build(); 170 | 171 | // 创建http GET请求 172 | HttpGet httpGet = new HttpGet(uri); 173 | 174 | //构造请求头 175 | if (headers != null && !headers.isEmpty()) { 176 | Set> headerEntrySet = headers.entrySet(); 177 | for (Map.Entry headerEntry : headerEntrySet) { 178 | httpGet.setHeader(headerEntry.getKey(), headerEntry.getValue()); 179 | } 180 | } 181 | // 执行请求 182 | response = httpclient.execute(httpGet); 183 | // 判断返回状态是否为200 184 | if (response.getStatusLine().getStatusCode() == 200) { 185 | resultString = EntityUtils.toString(response.getEntity(), "UTF-8"); 186 | } 187 | } catch (Exception e) { 188 | e.printStackTrace(); 189 | } finally { 190 | if (response != null) { 191 | try { 192 | response.close(); 193 | } catch (IOException ex) { 194 | log.error("关闭HttpResponse失败.", ex); 195 | } 196 | } 197 | if (httpclient != null) { 198 | try { 199 | httpclient.close(); 200 | } catch (IOException ex) { 201 | log.error("关闭HttpClient失败.", ex); 202 | } 203 | } 204 | } 205 | log.info(loggerMsg.toString()); 206 | return resultString; 207 | } 208 | 209 | public static String get(String url) { 210 | CloseableHttpClient httpClient = HttpClients.createDefault(); 211 | CloseableHttpResponse response = null; 212 | String result = ""; 213 | try { 214 | HttpGet get = new HttpGet(url); 215 | 216 | response = httpClient.execute(get); 217 | HttpEntity entity = response.getEntity(); 218 | if (entity != null) { 219 | result = EntityUtils.toString(entity); 220 | return result; 221 | } 222 | } catch (HttpHostConnectException e) { 223 | log.error("连接失败:{}, {}", e.getHost(), e.getMessage()); 224 | return "{\"status\":\"999\"}"; 225 | } catch (IOException e) { 226 | log.error("http client get error"); 227 | } finally { 228 | release(httpClient, response); 229 | } 230 | return ""; 231 | } 232 | 233 | public static String post(HttpPost httpPost) { 234 | RequestConfig requestConfig = RequestConfig 235 | .custom() 236 | .setSocketTimeout(30000) 237 | .setConnectTimeout(30000) 238 | .build(); 239 | httpPost.setConfig(requestConfig); 240 | CloseableHttpClient httpClient = HttpClients.createDefault(); 241 | CloseableHttpResponse response = null; 242 | String result = ""; 243 | try { 244 | response = httpClient.execute(httpPost); 245 | HttpEntity entity = response.getEntity(); 246 | if (entity != null) { 247 | result = EntityUtils.toString(entity, StandardCharsets.UTF_8); 248 | log.info("result: {}", result); 249 | return result; 250 | } 251 | } catch (IOException ex) { 252 | log.error("{}", ex.getMessage()); 253 | } finally { 254 | release(httpClient, response); 255 | } 256 | 257 | return result; 258 | } 259 | 260 | public static void release(CloseableHttpClient httpClient, CloseableHttpResponse response) { 261 | try { 262 | if (response != null) { 263 | response.close(); 264 | } 265 | if (httpClient != null) { 266 | httpClient.close(); 267 | } 268 | } catch (IOException e) { 269 | log.error("资源释放报错:{}", e.getMessage()); 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/IpUtils.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import java.net.InetAddress; 5 | import java.net.UnknownHostException; 6 | 7 | /** 8 | * 获取IP方法 9 | * 10 | * @author Alan Turing 11 | */ 12 | public class IpUtils { 13 | public static String getIpAddr(HttpServletRequest request) { 14 | if (request == null) { 15 | return "unknown"; 16 | } 17 | String ip = request.getHeader("x-forwarded-for"); 18 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 19 | ip = request.getHeader("Proxy-Client-IP"); 20 | } 21 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 22 | ip = request.getHeader("X-Forwarded-For"); 23 | } 24 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 25 | ip = request.getHeader("WL-Proxy-Client-IP"); 26 | } 27 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 28 | ip = request.getHeader("X-Real-IP"); 29 | } 30 | 31 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 32 | ip = request.getRemoteAddr(); 33 | } 34 | 35 | return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; 36 | } 37 | 38 | public static boolean internalIp(String ip) { 39 | byte[] addr = textToNumericFormatV4(ip); 40 | return internalIp(addr) || "127.0.0.1".equals(ip); 41 | } 42 | 43 | private static boolean internalIp(byte[] addr) { 44 | if (addr == null || addr.length < 2) { 45 | return true; 46 | } 47 | final byte b0 = addr[0]; 48 | final byte b1 = addr[1]; 49 | // 10.x.x.x/8 50 | final byte SECTION_1 = 0x0A; 51 | // 172.16.x.x/12 52 | final byte SECTION_2 = (byte) 0xAC; 53 | final byte SECTION_3 = (byte) 0x10; 54 | final byte SECTION_4 = (byte) 0x1F; 55 | // 192.168.x.x/16 56 | final byte SECTION_5 = (byte) 0xC0; 57 | final byte SECTION_6 = (byte) 0xA8; 58 | switch (b0) { 59 | case SECTION_1: 60 | return true; 61 | case SECTION_2: 62 | if (b1 >= SECTION_3 && b1 <= SECTION_4) { 63 | return true; 64 | } 65 | case SECTION_5: 66 | switch (b1) { 67 | case SECTION_6: 68 | return true; 69 | } 70 | default: 71 | return false; 72 | } 73 | } 74 | 75 | /** 76 | * 将IPv4地址转换成字节 77 | * 78 | * @param text IPv4地址 79 | * @return byte 字节 80 | */ 81 | public static byte[] textToNumericFormatV4(String text) { 82 | if (text.length() == 0) { 83 | return null; 84 | } 85 | 86 | byte[] bytes = new byte[4]; 87 | String[] elements = text.split("\\.", -1); 88 | try { 89 | long l; 90 | int i; 91 | switch (elements.length) { 92 | case 1: 93 | l = Long.parseLong(elements[0]); 94 | if ((l < 0L) || (l > 4294967295L)) 95 | return null; 96 | bytes[0] = (byte) (int) (l >> 24 & 0xFF); 97 | bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); 98 | bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); 99 | bytes[3] = (byte) (int) (l & 0xFF); 100 | break; 101 | case 2: 102 | l = Integer.parseInt(elements[0]); 103 | if ((l < 0L) || (l > 255L)) 104 | return null; 105 | bytes[0] = (byte) (int) (l & 0xFF); 106 | l = Integer.parseInt(elements[1]); 107 | if ((l < 0L) || (l > 16777215L)) 108 | return null; 109 | bytes[1] = (byte) (int) (l >> 16 & 0xFF); 110 | bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); 111 | bytes[3] = (byte) (int) (l & 0xFF); 112 | break; 113 | case 3: 114 | for (i = 0; i < 2; ++i) { 115 | l = Integer.parseInt(elements[i]); 116 | if ((l < 0L) || (l > 255L)) 117 | return null; 118 | bytes[i] = (byte) (int) (l & 0xFF); 119 | } 120 | l = Integer.parseInt(elements[2]); 121 | if ((l < 0L) || (l > 65535L)) 122 | return null; 123 | bytes[2] = (byte) (int) (l >> 8 & 0xFF); 124 | bytes[3] = (byte) (int) (l & 0xFF); 125 | break; 126 | case 4: 127 | for (i = 0; i < 4; ++i) { 128 | l = Integer.parseInt(elements[i]); 129 | if ((l < 0L) || (l > 255L)) 130 | return null; 131 | bytes[i] = (byte) (int) (l & 0xFF); 132 | } 133 | break; 134 | default: 135 | return null; 136 | } 137 | } catch (NumberFormatException e) { 138 | return null; 139 | } 140 | return bytes; 141 | } 142 | 143 | public static String getHostIp() { 144 | try { 145 | return InetAddress.getLocalHost().getHostAddress(); 146 | } catch (UnknownHostException e) { 147 | } 148 | return "127.0.0.1"; 149 | } 150 | 151 | public static String getHostName() { 152 | try { 153 | return InetAddress.getLocalHost().getHostName(); 154 | } catch (UnknownHostException e) { 155 | } 156 | return "未知"; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/JrebelSign.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | public class JrebelSign { 6 | private String signature; 7 | 8 | public void toLeaseCreateJson(String clientRandomness, final String guid, boolean offline, String validFrom, String validUntil) { 9 | String serverRandomness = "H2ulzLlh7E0="; //服务端随机数,如果要自己生成,务必将其写到json的serverRandomness中 10 | String s2= ""; 11 | if(offline){ 12 | s2 = StringUtils.join((Object[]) new String[]{clientRandomness, serverRandomness, guid, String.valueOf(offline), validFrom, validUntil}, ';'); 13 | }else{ 14 | s2 = StringUtils.join((Object[]) new String[]{clientRandomness, serverRandomness, guid, String.valueOf(offline)}, ';'); 15 | } 16 | System.out.println(s2); 17 | final byte[] a2 =LicenseServer2ToJRebelPrivateKey.a(s2.getBytes()); 18 | this.signature = ByteUtil.a(a2); 19 | } 20 | 21 | public String getSignature() { 22 | return signature; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/LicenseServer2ToJRebelPrivateKey.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 4 | 5 | import java.security.GeneralSecurityException; 6 | import java.security.KeyFactory; 7 | import java.security.PrivateKey; 8 | import java.security.Signature; 9 | import java.security.spec.PKCS8EncodedKeySpec; 10 | 11 | public class LicenseServer2ToJRebelPrivateKey { 12 | private static final String b = "MIICXAIBAAKBgQDQ93CP6SjEneDizCF1P/MaBGf582voNNFcu8oMhgdTZ/N6qa6O7XJDr1FSCyaDdKSsPCdxPK7Y4Usq/fOPas2kCgYcRS/iebrtPEFZ/7TLfk39HLuTEjzo0/CNvjVsgWeh9BYznFaxFDLx7fLKqCQ6w1OKScnsdqwjpaXwXqiulwIDAQABAoGATOQvvBSMVsTNQkbgrNcqKdGjPNrwQtJkk13aO/95ZJxkgCc9vwPqPrOdFbZappZeHa5IyScOI2nLEfe+DnC7V80K2dBtaIQjOeZQt5HoTRG4EHQaWoDh27BWuJoip5WMrOd+1qfkOtZoRjNcHl86LIAh/+3vxYyebkug4UHNGPkCQQD+N4ZUkhKNQW7mpxX6eecitmOdN7Yt0YH9UmxPiW1LyCEbLwduMR2tfyGfrbZALiGzlKJize38shGC1qYSMvZFAkEA0m6psWWiTUWtaOKMxkTkcUdigalZ9xFSEl6jXFB94AD+dlPS3J5gNzTEmbPLc14VIWJFkO+UOrpl77w5uF2dKwJAaMpslhnsicvKMkv31FtBut5iK6GWeEafhdPfD94/bnidpP362yJl8Gmya4cI1GXvwH3pfj8S9hJVA5EFvgTB3QJBAJP1O1uAGp46X7Nfl5vQ1M7RYnHIoXkWtJ417Kb78YWPLVwFlD2LHhuy/okT4fk8LZ9LeZ5u1cp1RTdLIUqAiAECQC46OwOm87L35yaVfpUIjqg/1gsNwNsj8HvtXdF/9d30JIM3GwdytCvNRLqP35Ciogb9AO8ke8L6zY83nxPbClM="; 13 | private static final byte[] c; 14 | private static final BouncyCastleProvider d; 15 | 16 | private static PrivateKey a() { 17 | final PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(LicenseServer2ToJRebelPrivateKey.c); 18 | try { 19 | return KeyFactory.getInstance("RSA", LicenseServer2ToJRebelPrivateKey.d).generatePrivate(pkcs8EncodedKeySpec); 20 | } catch (Exception ex) { 21 | ex.printStackTrace(); 22 | return null; 23 | } 24 | } 25 | 26 | public static byte[] a(final byte[] array) { 27 | try { 28 | final Signature instance = Signature.getInstance("SHA1withRSA", LicenseServer2ToJRebelPrivateKey.d); 29 | instance.initSign(a()); 30 | instance.update(array); 31 | return instance.sign(); 32 | } catch (GeneralSecurityException ex) { 33 | throw new RuntimeException("License Server installation error 0000000F2", ex); 34 | } 35 | } 36 | 37 | static { 38 | c = ByteUtil.a("MIICXAIBAAKBgQDQ93CP6SjEneDizCF1P/MaBGf582voNNFcu8oMhgdTZ/N6qa6O7XJDr1FSCyaDdKSsPCdxPK7Y4Usq/fOPas2kCgYcRS/iebrtPEFZ/7TLfk39HLuTEjzo0/CNvjVsgWeh9BYznFaxFDLx7fLKqCQ6w1OKScnsdqwjpaXwXqiulwIDAQABAoGATOQvvBSMVsTNQkbgrNcqKdGjPNrwQtJkk13aO/95ZJxkgCc9vwPqPrOdFbZappZeHa5IyScOI2nLEfe+DnC7V80K2dBtaIQjOeZQt5HoTRG4EHQaWoDh27BWuJoip5WMrOd+1qfkOtZoRjNcHl86LIAh/+3vxYyebkug4UHNGPkCQQD+N4ZUkhKNQW7mpxX6eecitmOdN7Yt0YH9UmxPiW1LyCEbLwduMR2tfyGfrbZALiGzlKJize38shGC1qYSMvZFAkEA0m6psWWiTUWtaOKMxkTkcUdigalZ9xFSEl6jXFB94AD+dlPS3J5gNzTEmbPLc14VIWJFkO+UOrpl77w5uF2dKwJAaMpslhnsicvKMkv31FtBut5iK6GWeEafhdPfD94/bnidpP362yJl8Gmya4cI1GXvwH3pfj8S9hJVA5EFvgTB3QJBAJP1O1uAGp46X7Nfl5vQ1M7RYnHIoXkWtJ417Kb78YWPLVwFlD2LHhuy/okT4fk8LZ9LeZ5u1cp1RTdLIUqAiAECQC46OwOm87L35yaVfpUIjqg/1gsNwNsj8HvtXdF/9d30JIM3GwdytCvNRLqP35Ciogb9AO8ke8L6zY83nxPbClM="); 39 | d = new BouncyCastleProvider(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/imjcker/jrebel/sys/rsasign.java: -------------------------------------------------------------------------------- 1 | package com.imjcker.jrebel.sys; 2 | 3 | import org.bouncycastle.asn1.ASN1InputStream; 4 | import org.bouncycastle.asn1.ASN1Primitive; 5 | import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; 6 | 7 | import java.security.KeyFactory; 8 | import java.security.PrivateKey; 9 | import java.security.spec.PKCS8EncodedKeySpec; 10 | import java.security.spec.RSAPrivateKeySpec; 11 | 12 | 13 | public class rsasign { 14 | static String header = "607875500OK15084842582741licensee=Administrator licenseType=0 "; 15 | static String content = "607875500OK15084842582741licensee=Administrator licenseType=0 "; 16 | String ASNKEY = "-----BEGIN RSA PRIVATE KEY-----\r\n" 17 | + "MIIBOgIBAAJBALecq3BwAI4YJZwhJ+snnDFj3lF3DMqNPorV6y5ZKXCiCMqj8OeOmxk4YZW9aaV9\r\n" 18 | + "ckl/zlAOI0mpB3pDT+Xlj2sCAwEAAQJAW6/aVD05qbsZHMvZuS2Aa5FpNNj0BDlf38hOtkhDzz/h\r\n" 19 | + "kYb+EBYLLvldhgsD0OvRNy8yhz7EjaUqLCB0juIN4QIhAOeCQp+NXxfBmfdG/S+XbRUAdv8iHBl+\r\n" 20 | + "F6O2wr5fA2jzAiEAywlDfGIl6acnakPrmJE0IL8qvuO3FtsHBrpkUuOnXakCIQCqdr+XvADI/UTh\r\n" 21 | + "TuQepuErFayJMBSAsNe3NFsw0cUxAQIgGA5n7ZPfdBi3BdM4VeJWb87WrLlkVxPqeDSbcGrCyMkC\r\n" 22 | + "IFSs5JyXvFTreWt7IQjDssrKDRIPmALdNjvfETwlNJyY\r\n" 23 | + "-----END RSA PRIVATE KEY-----"; 24 | String PCKS8KEY = "-----BEGIN PRIVATE KEY-----\r\n" 25 | + "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAt5yrcHAAjhglnCEn\r\n" 26 | + "6yecMWPeUXcMyo0+itXrLlkpcKIIyqPw546bGThhlb1ppX1ySX/OUA4jSakHekNP\r\n" 27 | + "5eWPawIDAQABAkBbr9pUPTmpuxkcy9m5LYBrkWk02PQEOV/fyE62SEPPP+GRhv4Q\r\n" 28 | + "Fgsu+V2GCwPQ69E3LzKHPsSNpSosIHSO4g3hAiEA54JCn41fF8GZ90b9L5dtFQB2\r\n" 29 | + "/yIcGX4Xo7bCvl8DaPMCIQDLCUN8YiXppydqQ+uYkTQgvyq+47cW2wcGumRS46dd\r\n" 30 | + "qQIhAKp2v5e8AMj9ROFO5B6m4SsVrIkwFICw17c0WzDRxTEBAiAYDmftk990GLcF\r\n" 31 | + "0zhV4lZvztasuWRXE+p4NJtwasLIyQIgVKzknJe8VOt5a3shCMOyysoNEg+YAt02\r\n" 32 | + "O98RPCU0nJg=\r\n" + "-----END PRIVATE KEY-----"; 33 | 34 | static String key22 = "MIIBOgIBAAJBALecq3BwAI4YJZwhJ+snnDFj3lF3DMqNPorV6y5ZKXCiCMqj8OeOmxk4YZW9aaV9" 35 | + "ckl/zlAOI0mpB3pDT+Xlj2sCAwEAAQJAW6/aVD05qbsZHMvZuS2Aa5FpNNj0BDlf38hOtkhDzz/h" 36 | + "kYb+EBYLLvldhgsD0OvRNy8yhz7EjaUqLCB0juIN4QIhAOeCQp+NXxfBmfdG/S+XbRUAdv8iHBl+" 37 | + "F6O2wr5fA2jzAiEAywlDfGIl6acnakPrmJE0IL8qvuO3FtsHBrpkUuOnXakCIQCqdr+XvADI/UTh" 38 | + "TuQepuErFayJMBSAsNe3NFsw0cUxAQIgGA5n7ZPfdBi3BdM4VeJWb87WrLlkVxPqeDSbcGrCyMkC" 39 | + "IFSs5JyXvFTreWt7IQjDssrKDRIPmALdNjvfETwlNJyY"; 40 | 41 | static String key33 = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAt5yrcHAAjhglnCEn" 42 | + "6yecMWPeUXcMyo0+itXrLlkpcKIIyqPw546bGThhlb1ppX1ySX/OUA4jSakHekNP" 43 | + "5eWPawIDAQABAkBbr9pUPTmpuxkcy9m5LYBrkWk02PQEOV/fyE62SEPPP+GRhv4Q" 44 | + "Fgsu+V2GCwPQ69E3LzKHPsSNpSosIHSO4g3hAiEA54JCn41fF8GZ90b9L5dtFQB2" 45 | + "/yIcGX4Xo7bCvl8DaPMCIQDLCUN8YiXppydqQ+uYkTQgvyq+47cW2wcGumRS46dd" 46 | + "qQIhAKp2v5e8AMj9ROFO5B6m4SsVrIkwFICw17c0WzDRxTEBAiAYDmftk990GLcF" 47 | + "0zhV4lZvztasuWRXE+p4NJtwasLIyQIgVKzknJe8VOt5a3shCMOyysoNEg+YAt02" 48 | + "O98RPCU0nJg="; 49 | 50 | public static String Sign(String content){ 51 | return rsasign.Sign(content.getBytes(), key22); 52 | } 53 | 54 | public static String Sign2(String content){ 55 | return rsasign.Sign2(content.getBytes(), key33); 56 | } 57 | 58 | //传入秘钥为ASN格式 59 | //私钥签名程序,privateKey是私钥base64编码字符串,即私钥文件数据中,中间的主体部分 60 | public static String Sign(byte[] content, String privateKey) { 61 | try { 62 | byte[] keybyte = Base64.decode(privateKey.toString()); 63 | ASN1InputStream in = new ASN1InputStream(keybyte); 64 | ASN1Primitive obj = in.readObject(); 65 | RSAPrivateKeyStructure pStruct = RSAPrivateKeyStructure.getInstance(obj); 66 | RSAPrivateKeySpec spec = new RSAPrivateKeySpec(pStruct.getModulus(), pStruct.getPrivateExponent()); 67 | KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 68 | PrivateKey priKey = keyFactory.generatePrivate(spec); 69 | java.security.Signature signature = java.security.Signature.getInstance("MD5WithRSA"); 70 | signature.initSign(priKey); 71 | signature.update(content); 72 | byte[] signed = signature.sign(); 73 | return Hex.bytesToHexString(signed); 74 | } 75 | catch (Exception e) { 76 | e.printStackTrace(); 77 | } 78 | return null; 79 | } 80 | 81 | //传入秘钥为PKCS#8私钥非加密格式 82 | //私钥签名程序,privateKey是私钥base64编码字符串,即私钥文件数据中,中间的主体部分 83 | public static String Sign2(byte[] content, String privateKey) { 84 | try { 85 | PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey)); 86 | KeyFactory keyf = KeyFactory.getInstance("RSA"); 87 | PrivateKey priKey = keyf.generatePrivate(priPKCS8); 88 | java.security.Signature signature = java.security.Signature.getInstance("MD5WithRSA"); 89 | signature.initSign(priKey); 90 | signature.update(content); 91 | byte[] signed = signature.sign(); 92 | return Hex.bytesToHexString(signed); 93 | } catch (Exception e) { 94 | e.printStackTrace(); 95 | } 96 | return null; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": [ 3 | { 4 | "name": "jrebel", 5 | "type": "com.imjcker.jrebel.config.JrebelConfigurationProperties", 6 | "sourceType": "com.imjcker.jrebel.config.JrebelConfigurationProperties" 7 | } 8 | ], 9 | "properties": [ 10 | { 11 | "name": "jrebel.social", 12 | "type": "java.util.List", 13 | "description": "social networks url list", 14 | "sourceType": "com.imjcker.jrebel.config.JrebelConfigurationProperties" 15 | }, 16 | { 17 | "name": "jrebel.url-cn", 18 | "type": "java.lang.String", 19 | "description": "jrebel active addr for China", 20 | "sourceType": "com.imjcker.jrebel.config.JrebelConfigurationProperties" 21 | }, 22 | { 23 | "name": "jrebel.url-global", 24 | "type": "java.lang.String", 25 | "description": "jrebel active addr for global", 26 | "sourceType": "com.imjcker.jrebel.config.JrebelConfigurationProperties" 27 | }, 28 | { 29 | "name": "jrebel.ip-fetch-url", 30 | "type": "java.lang.String", 31 | "description": "获取jrebel部署服务器的公网IP地址", 32 | "sourceType": "com.imjcker.jrebel.config.JrebelConfigurationProperties", 33 | "deprecated": true, 34 | "deprecation": {} 35 | } 36 | ], 37 | "hints": [] 38 | } -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: jrebel-license-server 4 | freemarker: 5 | enabled: true 6 | prefix: / 7 | suffix: .ftl 8 | template-loader-path: classpath:/templates/ 9 | mvc: 10 | static-path-pattern: /** 11 | main: 12 | allow-bean-definition-overriding: true 13 | 14 | logging: 15 | level: 16 | org.springframework.web: INFO 17 | com.imjcker.jrebel: DEBUG 18 | file: 19 | name: ${user.home}/.${spring.application.name}/logs/jrebel.log 20 | logback: 21 | rollingpolicy: 22 | max-history: 7 23 | max-file-size: 10MB 24 | 25 | server: 26 | port: 9090 27 | 28 | jrebel: 29 | url-cn: https://jrebel.imjcker.com:1314 30 | url-global: https://jrebel.hk.imjcker.com 31 | social: 32 | - name: CSDN 33 | url: https://blog.csdn.net/u012137018 34 | - name: 博客园 35 | url: https://www.cnblogs.com/tfsc/ 36 | - name: GitHub 37 | url: https://github.com/everydoc 38 | - name: 个人博客 39 | url: https://blog.hk.imjcker.com 40 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ,--. ,--. ,--. 3 | `--',--,--,--. `--' ,---.| |,-. ,---. ,--.--. ,---. ,---. ,--,--,--. 4 | ,--.| | ,--.| .--'| /| .-. :| .--' | .--'| .-. || | 5 | | || | | | | |\ `--.| \ \\ --.| |.--.\ `--.' '-' '| | | | 6 | `--'`--`--`--'.-' / `---'`--'`--'`----'`--''--' `---' `---' `--`--`--' spring boot ${spring-boot.formatted-version} 7 | '---' ${spring.application.name} 8 | ======================================================================== Alan Turing. 9 | 10 | -------------------------------------------------------------------------------- /src/main/resources/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/src/main/resources/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/rebel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | jrebel-license-server 10 | 11 | 12 |

13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/static/mini-program.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/src/main/resources/static/mini-program.jpg -------------------------------------------------------------------------------- /src/main/resources/static/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daimazhan/jrebel-license-server/bf05629f5d3f6847ad35e9ba840ea62a29348fac/src/main/resources/static/wechat.jpg -------------------------------------------------------------------------------- /src/main/resources/templates/index.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | License Server 6 | 7 | 8 | 9 |
10 | 16 | 17 |
18 |

Jrebel & JetBrains License Server!

19 |

JRebel 2018.1 and later version Activation address is: ${uuid}

20 | 21 |

22 | <#list jrebel.social as s> 23 | ${s.name}   24 | 25 |

26 | 27 | 28 |

关注公众号【天府书虫】,发送关键字"jrebel"获取激活地址。

29 | 微信公众号 30 | <#-- 小程序--> 31 |
32 |

33 | Fork me on GitHub 34 |

35 |
36 |
37 | 38 | 39 | 40 | <#----> 41 | 42 | 43 | 44 | 76 | 77 | 78 | --------------------------------------------------------------------------------