init: 简单的验证授权
This commit is contained in:
47
.gitignore
vendored
Normal file
47
.gitignore
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/modules.xml
|
||||||
|
.idea/jarRepositories.xml
|
||||||
|
.idea/compiler.xml
|
||||||
|
.idea/libraries/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
||||||
|
/.idea/
|
||||||
|
/.idea/.gitignore
|
||||||
|
/.idea/compiler.xml
|
||||||
|
/.idea/encodings.xml
|
||||||
|
/.idea/jarRepositories.xml
|
||||||
|
/.idea/misc.xml
|
||||||
|
/.idea/uiDesigner.xml
|
||||||
|
/.idea/vcs.xml
|
||||||
|
/.idea/workspace.xml
|
||||||
39
nl-verify-check-sdk/pom.xml
Normal file
39
nl-verify-check-sdk/pom.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.nl</groupId>
|
||||||
|
<artifactId>nl-verify-check</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nl-verify-check-sdk</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>2.7.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.22</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.83</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package org.nl.core;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import org.nl.util.RSAUtil;
|
||||||
|
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/26
|
||||||
|
*/
|
||||||
|
public class AuthInterceptor extends HandlerInterceptorAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
String authCode = request.getHeader("cdk"); // 假设从 Header 获取
|
||||||
|
|
||||||
|
if (authCode == null || authCode.isEmpty()) {
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
response.setStatus(402);
|
||||||
|
response.getWriter().write(JSONObject.toJSONString(LicenseResult.requestResult(false, "请收入授权码", null)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String expirationStr ="";
|
||||||
|
try {
|
||||||
|
// 解密获取到期时间
|
||||||
|
expirationStr = RSAUtil.decrypt(authCode);
|
||||||
|
if ("-1".equals(expirationStr)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LocalDate expirationDate = LocalDate.parse(expirationStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
if (LocalDate.now().isAfter(expirationDate)) {
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
response.setStatus(402);
|
||||||
|
response.getWriter().write(JSONObject.toJSONString(LicenseResult.requestResult(false, "授权码已到期", null)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 解密失败或格式错误
|
||||||
|
response.setContentType("text/html;charset=UTF-8");
|
||||||
|
response.setStatus(402);
|
||||||
|
response.getWriter().write(JSONObject.toJSONString(LicenseResult.requestResult(false, "解密失败或格式错误", null)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package org.nl.core;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/14
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public class LicenseResult {
|
||||||
|
/** 检验结果 */
|
||||||
|
private Boolean result;
|
||||||
|
/** 附加信息 */
|
||||||
|
private String message;
|
||||||
|
/** 证书key */
|
||||||
|
private String content;
|
||||||
|
public static LicenseResult requestResult(Boolean result, String message, String content) {
|
||||||
|
return LicenseResult.builder()
|
||||||
|
.message(message)
|
||||||
|
.result(result)
|
||||||
|
.content(content)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
public static LicenseResult requestOk(String message, String content) {
|
||||||
|
return LicenseResult.builder()
|
||||||
|
.message(message)
|
||||||
|
.result(true)
|
||||||
|
.content(content)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
17
nl-verify-check-sdk/src/main/java/org/nl/core/WebConfig.java
Normal file
17
nl-verify-check-sdk/src/main/java/org/nl/core/WebConfig.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package org.nl.core;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/26
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class WebConfig implements WebMvcConfigurer {
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/**");
|
||||||
|
}
|
||||||
|
}
|
||||||
47
nl-verify-check-sdk/src/main/java/org/nl/util/RSAUtil.java
Normal file
47
nl-verify-check-sdk/src/main/java/org/nl/util/RSAUtil.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package org.nl.util;
|
||||||
|
|
||||||
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/13
|
||||||
|
*/
|
||||||
|
public class RSAUtil {
|
||||||
|
private static PrivateKey privateKey;
|
||||||
|
|
||||||
|
public static synchronized PrivateKey getPrivateKey() throws Exception {
|
||||||
|
if (privateKey == null) {
|
||||||
|
// 从 resources/private_key.txt 读取 Base64
|
||||||
|
String filePath = ResourceUtils.getFile("classpath:private_key.txt").getPath();
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(filePath));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
byte[] privateKeyBytes = Base64.getDecoder().decode(sb.toString());
|
||||||
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
privateKey = keyFactory.generatePrivate(keySpec);
|
||||||
|
}
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String decrypt(String authCode) throws Exception {
|
||||||
|
byte[] encryptedBytes = Base64.getDecoder().decode(authCode);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey());
|
||||||
|
byte[] decrypted = cipher.doFinal(encryptedBytes);
|
||||||
|
return new String(decrypted, "UTF-8");
|
||||||
|
}
|
||||||
|
}
|
||||||
1
nl-verify-check-sdk/src/main/resources/private_key.txt
Normal file
1
nl-verify-check-sdk/src/main/resources/private_key.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCBbWQ38mZdmOX379myX/NFn/qFIeP3kbogDiWlGtc1JNt6eDSsOEShUNj3o8Jo5Qaepyo6j4stP4WpmCAUFsdyOodzU0R60P7gFOR1OIdKyyQ2OS9J1MdNXRRuksfD1WVG+azoB+huQo2D52bcXSjnu1UDRDrXN3XXZgh1L2V/aDg+Gi9QAIsMDHtN62zKsHs4tlClHt0KORSdAxN9RjPzUFNYXfxW3dNTM9zfltoM2bgeUfG61F5EMipkAEVjDb4+Pu2BsNUamjy85eKDWA8NxDU6uuDkxLNiLx5KipLxOR+EM4/cOqRwHdEj8matpGlqBSOfOxXd6Sh5XmVStBjtAgMBAAECggEAQCbcme6IVrRGqJI2MXfluQkGv56AxGFzBBh/CEs5iJnwP8/9K6/oNJ1CLdz5q8x5b4IkKEqmDZOCyQEiRVLVIQVpxfvr4YReEOvKIWAXjzcJh+boTYwuDWapjfUrFyJaxMdUsN3ak2xhgJPeJDP45oOwK6JSGALhYhas8oi/olptl3leZs/5Z3h9UE69u80XRdhjtGyfS3AOOtT6dVcfKw6H8tmoKmx43ZfPvoV+a7hcwHO587mI1epAhYGOn81e5QoNBegiCEv9KutuZtauJuGHKcsvNh/FK8QujRJ1TFxOsMtxsJWZfxQxUuvJ0PulCpGpmkuHFNGDmV3ukJO1AQKBgQC8eiTaWgq8eCrIOi5fYtXQUmzv2e5BOhMrRyUWoB30N7GmKcdNGT5HJVXztidcBj53cNd8T6t5yTwYFrdZ5Lll7ItPAub25CSnGQU2nmceHK+46PNlQfLZRrlyeUuGYJTHVZanV+6Pneqn+6XifTa969HzpejpiJuG8iYVmcztfQKBgQCvy5ha6tBS+sIrjXL8/lrxXMDm4xT3CnCLmBqInppLwfFOgcQFzYWL6SQSJ7k3uC+xFT++VgsRLz/pQrVLsQzkY6mUF8sI7F0kevy/jAFzl9cgFn9BXu1ATyWloQIAX/UdSbzSWxIH3BW3BNOWZ0x91HUqBDAFzyLBkIns8LZ0MQKBgQCyg9oN+kS69/JFjV3IuLsdQkSt9LNGknP/hLYrNOLKIkofwOhlLOigyEsdt0SWU8+sn3Np6afXhPNnOXTWLt4vHJlh77TE2ZehsQAQGH5Athj1waZvHMSgaO1S8HHJSAcCuh0kSRPKcV8FVkNrPv+vaQGFjXoKX3o3mXja8r53nQKBgQCElQVj1GKnoo1csYJ+wgqurCikObFvG8WD0oR4cz2lUzD956qCQd2thnj45FKxbk0xvffkQhp4rG0ELJZ07qPtgCi+Ey/CnBknUUZb5GiX2HWbsrvo/oHqlYasIwFSbQx9OUaaU6sGmHscHBzD+0ZaRCjVNnFNgEoTOEJ9m5HPkQKBgQC0Kd29rQMIm5wXhIyW+bVdwmEyB/Xuq6Ch7lVVfZ6WMSoDbQZdYH3Mxw+yzjYpcS8jf/7x7mYH9Z0ggXwX7CAcRqhpjtKU800KzwQ2Cnd7Jmgq56Mn/e70J4btH73EZB6sm7vmhIuBZZlvc3oYGeJN/t/9vLwomFqrlXVw318J2A==
|
||||||
28
nl-verify-check-test/pom.xml
Normal file
28
nl-verify-check-test/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.nl</groupId>
|
||||||
|
<artifactId>nl-verify-check</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>nl-verify-check-test</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.nl</groupId>
|
||||||
|
<artifactId>nl-verify-check-sdk</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package org.nl;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/13
|
||||||
|
*/
|
||||||
|
public class GenerateAuthCode {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgW1kN/JmXZjl9+/Zsl/zRZ/6hSHj95G6IA4lpRrXNSTbeng0rDhEoVDY96PCaOUGnqcqOo+LLT+FqZggFBbHcjqHc1NEetD+4BTkdTiHSsskNjkvSdTHTV0UbpLHw9VlRvms6AfobkKNg+dm3F0o57tVA0Q61zd112YIdS9lf2g4PhovUACLDAx7TetsyrB7OLZQpR7dCjkUnQMTfUYz81BTWF38Vt3TUzPc35baDNm4HlHxutReRDIqZABFYw2+Pj7tgbDVGpo8vOXig1gPDcQ1Orrg5MSzYi8eSoqS8TkfhDOP3DqkcB3RI/JmraRpagUjnzsV3ekoeV5lUrQY7QIDAQAB"; // 从生成器中获取
|
||||||
|
String expirationDate = "2025-12-31"; // 到期时间原文
|
||||||
|
|
||||||
|
// 还原公钥
|
||||||
|
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(keySpec);
|
||||||
|
|
||||||
|
// 加密
|
||||||
|
// Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // 标准填充模式
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA"); // 标准填充模式
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
byte[] encrypted = cipher.doFinal(expirationDate.getBytes("UTF-8"));
|
||||||
|
String authCode = Base64.getEncoder().encodeToString(encrypted);
|
||||||
|
|
||||||
|
System.out.println("授权码: " + authCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
nl-verify-check-test/src/main/java/org/nl/Main.java
Normal file
11
nl-verify-check-test/src/main/java/org/nl/Main.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package org.nl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: ${DATE}
|
||||||
|
*/
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello world!");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package org.nl;
|
||||||
|
|
||||||
|
import java.security.*;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: 2025/8/13
|
||||||
|
*/
|
||||||
|
public class RSAKeyGenerator {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyGen.initialize(2048); // 推荐 2048 位密钥,安全级别高
|
||||||
|
KeyPair pair = keyGen.generateKeyPair();
|
||||||
|
PrivateKey privateKey = pair.getPrivate();
|
||||||
|
PublicKey publicKey = pair.getPublic();
|
||||||
|
|
||||||
|
// Base64 编码,便于存储和传输
|
||||||
|
String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
|
||||||
|
String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
|
||||||
|
|
||||||
|
System.out.println("Private Key (Base64): " + privateKeyBase64);
|
||||||
|
System.out.println("Public Key (Base64): " + publicKeyBase64);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
pom.xml
Normal file
22
pom.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.nl</groupId>
|
||||||
|
<artifactId>nl-verify-check</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>nl-verify-check-sdk</module>
|
||||||
|
<module>nl-verify-check-test</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
11
src/main/java/org/nl/Main.java
Normal file
11
src/main/java/org/nl/Main.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package org.nl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: lyd
|
||||||
|
* @Date: ${DATE}
|
||||||
|
*/
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello world!");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user