Compare commits

...

9 commits

Author SHA1 Message Date
Metall
7cf02eb095
Merge 05530b6664 into 9e29053afa 2025-03-18 13:28:18 +01:00
Gravita
9e29053afa [FEATURE] Setup support env configuration in ServerWrapper, fix compile 2025-02-24 19:47:41 +07:00
Gravita
2e93102106 [FEATURE] Add serverName to env configuration in ServerWrapper 2025-02-24 19:21:10 +07:00
Gravita
d4b69195b3 [FEATURE] Support env configuration in ServerWrapper 2025-02-24 19:18:49 +07:00
Metall
05530b6664
Merge branch 'GravitLauncher:master' into master 2024-07-23 20:33:25 +05:00
Metall
8f20cbe104
Merge branch 'GravitLauncher:master' into master 2023-03-27 20:27:50 +05:00
Metall
66d8b9d9ca
Update PasswordVerifier.java
Убрал исключения для совместимости
2022-09-21 09:29:13 +05:00
Metall
90ee90973e
Update PasswordVerifier.java
Добавил:
1. Способ верификации "django", для осуществления авторизации с помощью PBKDF2 с SHA256.
2. Исключение на отсутствующий алгоритм(NoSuchAlgorithmException)
3. Исключение на неверные ключи(InvalidKeySpecException)
2022-09-21 08:40:40 +05:00
Metall
8bf58cff18
Create DjangoPasswordVerifier.java
Верификация PBKDF2_SHA256
2022-09-21 08:32:53 +05:00
10 changed files with 119 additions and 15 deletions

View file

@ -0,0 +1,42 @@
package pro.gravit.launchserver.auth.password;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.bouncycastle.crypto.params.KeyParameter;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class DjangoPasswordVerifier extends PasswordVerifier {
public final Integer DEFAULT_ITERATIONS = 10000;
private static final Logger logger = LogManager.getLogger();
private static final String algorithm = "pbkdf2_sha256";
public String getEncodedHash(String password, String salt, int iterations) {
PKCS5S2ParametersGenerator generator = new PKCS5S2ParametersGenerator(new SHA256Digest());
generator.init(password.getBytes(StandardCharsets.UTF_8), salt.getBytes(), iterations);
byte[] dk = ((KeyParameter) generator.generateDerivedParameters(256)).getKey();
byte[] hashBase64 = Base64.getEncoder().encode(dk);
return new String(hashBase64);
}
public String encode(String password, String salt, int iterations) {
String hash = getEncodedHash(password, salt, iterations);
return String.format("%s$%d$%s$%s", algorithm, iterations, salt, hash);
}
@Override
public boolean check(String encryptedPassword, String password) {
String[] params = encryptedPassword.split("\\$");
if (params.length != 4) {
logger.warn(" end 1 " + params.length);
return false;
}
int iterations = Integer.parseInt(params[1]);
String salt = params[2];
String hash = encode(password, salt, iterations);
return hash.equals(encryptedPassword);
}
}

View file

@ -15,6 +15,7 @@ public static void registerProviders() {
providers.register("bcrypt", BCryptPasswordVerifier.class);
providers.register("accept", AcceptPasswordVerifier.class);
providers.register("reject", RejectPasswordVerifier.class);
providers.register("django", DjangoPasswordVerifier.class);
registeredProviders = true;
}
}

View file

@ -154,7 +154,7 @@ public static String getRefreshToken() {
public static void reconnect() throws Exception {
getRequestService().open();
getRequestService().connect();
restore();
}

View file

@ -6,7 +6,7 @@
public interface RequestService {
<T extends WebSocketEvent> CompletableFuture<T> request(Request<T> request) throws IOException;
void open();
void connect() throws Exception;
void registerEventHandler(EventHandler handler);

View file

@ -9,6 +9,7 @@
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@ -63,7 +64,7 @@ public ClientJSONPoint(URI uri) {
}
}
public void open() throws Exception {
public void connect() throws Exception {
webSocket = webSocketBuilder.buildAsync(uri, this).get();
}
@ -97,6 +98,17 @@ public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String re
return WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
}
@Override
public void onOpen(WebSocket webSocket) {
onOpen();
WebSocket.Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onBinary(WebSocket webSocket, ByteBuffer data, boolean last) {
return WebSocket.Listener.super.onBinary(webSocket, data, last);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
LogHelper.error(error);

View file

@ -45,7 +45,7 @@ public <T extends WebSocketEvent> CompletableFuture<T> request(Request<T> reques
}
@Override
public void open() {
public void connect() {
}

View file

@ -11,9 +11,12 @@
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;

View file

@ -26,7 +26,7 @@ public <T extends WebSocketEvent> CompletableFuture<T> request(Request<T> reques
}
@Override
public void open() {
public void connect() {
}

View file

@ -32,6 +32,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> {
@ -121,6 +122,7 @@ public void run(String... args) throws Throwable {
}
LogHelper.debug("Read ServerWrapperConfig.json");
loadConfig();
config.applyEnv();
updateLauncherConfig();
Launcher.applyLauncherEnv(Objects.requireNonNullElse(config.env, LauncherConfig.LauncherEnvironment.STD));
StdWebSocketService service = StdWebSocketService.initWebSockets(config.address).get();
@ -304,5 +306,38 @@ public void apply() {
ConfigService.checkServerConfig.needProperties = checkServerNeedProperties;
}
}
public void applyEnv() {
this.authId = applyEnvOrDefault("SERVERWRAPPER_AUTH_ID", this.authId);
this.address = applyEnvOrDefault("SERVERWRAPPER_ADDRESS", this.address);
this.serverName = applyEnvOrDefault("SERVERWRAPPER_SERVER_NAME", this.serverName);
this.encodedServerEcPublicKey = applyEnvOrDefault("SERVERWRAPPER_EC_PUBLIC_KEY", Base64.getUrlDecoder()::decode, null);
this.encodedServerRsaPublicKey = applyEnvOrDefault("SERVERWRAPPER_RSA_PUBLIC_KEY", Base64.getUrlDecoder()::decode, null);
{
String token = System.getenv("SERVERWRAPPER_CHECK_SERVER_TOKEN");
if(token != null) {
if(extendedTokens == null) {
extendedTokens = new HashMap<>();
}
extendedTokens.put("checkServer", new Request.ExtendedToken(token, 0L));
}
}
}
private static String applyEnvOrDefault(String envName, String def) {
String value = System.getenv(envName);
if(value == null) {
return def;
}
return value;
}
private static<T> T applyEnvOrDefault(String envName, Function<String, T> mappingFunction, T def) {
String value = System.getenv(envName);
if(value == null) {
return def;
}
return mappingFunction.apply(value);
}
}
}

View file

@ -30,8 +30,11 @@ public ServerWrapperSetup() throws IOException {
public void run() throws Exception {
ServerWrapper wrapper = ServerWrapper.wrapper;
System.out.println("Print server jar filename:");
String jarName = commands.commandHandler.readLine();
String jarName = System.getenv("SERVERWRAPPER_JAR_NAME");
if(jarName == null) {
System.out.println("Print server jar filename:");
jarName = commands.commandHandler.readLine();
}
Path jarPath = Paths.get(jarName);
String mainClassName;
String agentClassName;
@ -56,14 +59,18 @@ public void run() throws Exception {
if (agentClassName != null) {
LogHelper.info("Found PremainClass %s", agentClassName);
}
System.out.println("Print your server name:");
wrapper.config.serverName = commands.commandHandler.readLine();
if(wrapper.config.serverName == null || wrapper.config.serverName.isEmpty()) {
System.out.println("Print your server name:");
wrapper.config.serverName = commands.commandHandler.readLine();
}
wrapper.config.mainclass = mainClassName;
boolean altMode = false;
for (int i = 0; i < 10; ++i) {
if(!Request.isAvailable() || Request.getRequestService().isClosed()) {
System.out.println("Print launchserver websocket host( ws://host:port/api ):");
wrapper.config.address = commands.commandHandler.readLine();
if(wrapper.config.address == null || wrapper.config.address.isEmpty()) {
System.out.println("Print launchserver websocket host( ws://host:port/api ):");
wrapper.config.address = commands.commandHandler.readLine();
}
StdWebSocketService service;
try {
service = StdWebSocketService.initWebSockets(wrapper.config.address).get();
@ -73,9 +80,11 @@ public void run() throws Exception {
}
Request.setRequestService(service);
}
System.out.println("Print server token:");
String checkServerToken = commands.commandHandler.readLine();
wrapper.config.extendedTokens.put("checkServer", new Request.ExtendedToken(checkServerToken, 0));
if(wrapper.config.extendedTokens == null || wrapper.config.extendedTokens.get("checkServer") == null) {
System.out.println("Print server token:");
String checkServerToken = commands.commandHandler.readLine();
wrapper.config.extendedTokens.put("checkServer", new Request.ExtendedToken(checkServerToken, 0));
}
wrapper.updateLauncherConfig();
try {
wrapper.restore();
@ -93,7 +102,9 @@ public void run() throws Exception {
}
if(wrapper.profile != null && wrapper.profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_18) >= 0) {
LogHelper.info("Switch to alternative start mode (1.18)");
wrapper.config.classpath.add(jarName);
if(!wrapper.config.classpath.contains(jarName)) {
wrapper.config.classpath.add(jarName);
}
wrapper.config.classLoaderConfig = ClientProfile.ClassLoaderConfig.LAUNCHER;
altMode = true;
}