mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
[FEATURE] ProtectHandler
This commit is contained in:
parent
7e5fafa159
commit
37be6b86c3
13 changed files with 152 additions and 1 deletions
|
@ -8,6 +8,8 @@
|
||||||
import ru.gravit.launcher.managers.GarbageManager;
|
import ru.gravit.launcher.managers.GarbageManager;
|
||||||
import ru.gravit.launcher.profiles.ClientProfile;
|
import ru.gravit.launcher.profiles.ClientProfile;
|
||||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||||
|
import ru.gravit.launchserver.auth.protect.NoProtectHandler;
|
||||||
|
import ru.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import ru.gravit.launchserver.components.AuthLimiterComponent;
|
import ru.gravit.launchserver.components.AuthLimiterComponent;
|
||||||
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
import ru.gravit.launchserver.auth.handler.MemoryAuthHandler;
|
||||||
|
@ -89,6 +91,8 @@ public static final class Config {
|
||||||
|
|
||||||
public AuthHandler authHandler;
|
public AuthHandler authHandler;
|
||||||
|
|
||||||
|
public ProtectHandler protectHandler;
|
||||||
|
|
||||||
public PermissionsHandler permissionsHandler;
|
public PermissionsHandler permissionsHandler;
|
||||||
|
|
||||||
public TextureProvider textureProvider;
|
public TextureProvider textureProvider;
|
||||||
|
@ -159,6 +163,10 @@ public void verify() {
|
||||||
if (authHandler == null) {
|
if (authHandler == null) {
|
||||||
throw new NullPointerException("AuthHandler must not be null");
|
throw new NullPointerException("AuthHandler must not be null");
|
||||||
}
|
}
|
||||||
|
if(protectHandler == null)
|
||||||
|
{
|
||||||
|
throw new NullPointerException("ProtectHandler must not be null");
|
||||||
|
}
|
||||||
if (authProvider == null || authProvider[0] == null) {
|
if (authProvider == null || authProvider[0] == null) {
|
||||||
throw new NullPointerException("AuthProvider must not be null");
|
throw new NullPointerException("AuthProvider must not be null");
|
||||||
}
|
}
|
||||||
|
@ -377,6 +385,7 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
|
||||||
PermissionsHandler.registerHandlers();
|
PermissionsHandler.registerHandlers();
|
||||||
Response.registerResponses();
|
Response.registerResponses();
|
||||||
Component.registerComponents();
|
Component.registerComponents();
|
||||||
|
ProtectHandler.registerHandlers();
|
||||||
LaunchServer.server = this;
|
LaunchServer.server = this;
|
||||||
|
|
||||||
// Set command handler
|
// Set command handler
|
||||||
|
@ -435,6 +444,10 @@ public LaunchServer(Path dir, String[] args) throws IOException, InvalidKeySpecE
|
||||||
for (AuthProvider provider : config.authProvider) {
|
for (AuthProvider provider : config.authProvider) {
|
||||||
provider.init();
|
provider.init();
|
||||||
}
|
}
|
||||||
|
if(config.protectHandler != null)
|
||||||
|
{
|
||||||
|
config.protectHandler.checkLaunchServerLicense();
|
||||||
|
}
|
||||||
config.authHandler.init();
|
config.authHandler.init();
|
||||||
if(config.components != null)
|
if(config.components != null)
|
||||||
{
|
{
|
||||||
|
@ -546,6 +559,7 @@ public static void initGson() {
|
||||||
Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
|
Launcher.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
|
||||||
Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
|
Launcher.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
|
||||||
Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
|
Launcher.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
|
||||||
|
Launcher.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter());
|
||||||
Launcher.gson = Launcher.gsonBuilder.create();
|
Launcher.gson = Launcher.gsonBuilder.create();
|
||||||
|
|
||||||
//Human readable
|
//Human readable
|
||||||
|
@ -557,6 +571,7 @@ public static void initGson() {
|
||||||
LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
|
LaunchServer.gsonBuilder.registerTypeAdapter(PermissionsHandler.class, new PermissionsHandlerAdapter());
|
||||||
LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
|
LaunchServer.gsonBuilder.registerTypeAdapter(HWIDHandler.class, new HWIDHandlerAdapter());
|
||||||
LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
|
LaunchServer.gsonBuilder.registerTypeAdapter(Component.class, new ComponentAdapter());
|
||||||
|
LaunchServer.gsonBuilder.registerTypeAdapter(ProtectHandler.class, new ProtectHandlerAdapter());
|
||||||
LaunchServer.gson = LaunchServer.gsonBuilder.create();
|
LaunchServer.gson = LaunchServer.gsonBuilder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,6 +623,7 @@ private void generateConfigIfNotExists() throws IOException {
|
||||||
newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh";
|
newConfig.startScript = JVMHelper.OS_TYPE.equals(JVMHelper.OS.MUSTDIE) ? "." + File.separator + "start.bat" : "." + File.separator + "start.sh";
|
||||||
newConfig.authHandler = new MemoryAuthHandler();
|
newConfig.authHandler = new MemoryAuthHandler();
|
||||||
newConfig.hwidHandler = new AcceptHWIDHandler();
|
newConfig.hwidHandler = new AcceptHWIDHandler();
|
||||||
|
newConfig.protectHandler = new NoProtectHandler();
|
||||||
|
|
||||||
newConfig.authProvider = new AuthProvider[]{new RejectAuthProvider("Настройте authProvider")};
|
newConfig.authProvider = new AuthProvider[]{new RejectAuthProvider("Настройте authProvider")};
|
||||||
newConfig.textureProvider = new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png");
|
newConfig.textureProvider = new RequestTextureProvider("http://example.com/skins/%username%.png", "http://example.com/cloaks/%username%.png");
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ru.gravit.launchserver.auth.protect;
|
||||||
|
|
||||||
|
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||||
|
import ru.gravit.utils.helper.SecurityHelper;
|
||||||
|
|
||||||
|
public class NoProtectHandler extends ProtectHandler {
|
||||||
|
@Override
|
||||||
|
public String generateSecureToken(AuthResponse.AuthContext context) {
|
||||||
|
return SecurityHelper.randomStringToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkLaunchServerLicense() {
|
||||||
|
// None
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package ru.gravit.launchserver.auth.protect;
|
||||||
|
|
||||||
|
import ru.gravit.launchserver.auth.AuthException;
|
||||||
|
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
|
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||||
|
import ru.gravit.utils.helper.VerifyHelper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public abstract class ProtectHandler {
|
||||||
|
private static final Map<String, Class<? extends ProtectHandler>> PROTECT_HANDLERS = new ConcurrentHashMap<>(4);
|
||||||
|
private static boolean registredHandl = false;
|
||||||
|
|
||||||
|
|
||||||
|
public static void registerHandler(String name, Class<? extends ProtectHandler> adapter) {
|
||||||
|
VerifyHelper.verifyIDName(name);
|
||||||
|
VerifyHelper.putIfAbsent(PROTECT_HANDLERS, name, Objects.requireNonNull(adapter, "adapter"),
|
||||||
|
String.format("Protect handler has been already registered: '%s'", name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<? extends ProtectHandler> getHandlerClass(String name) {
|
||||||
|
return PROTECT_HANDLERS.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHandlerName(Class<ProtectHandler> clazz) {
|
||||||
|
for (Map.Entry<String, Class<? extends ProtectHandler>> e : PROTECT_HANDLERS.entrySet()) {
|
||||||
|
if (e.getValue().equals(clazz)) return e.getKey();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerHandlers() {
|
||||||
|
if (!registredHandl) {
|
||||||
|
registerHandler("none", NoProtectHandler.class);
|
||||||
|
registredHandl = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface
|
||||||
|
|
||||||
|
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
|
||||||
|
//public abstract
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ru.gravit.launchserver.config;
|
||||||
|
|
||||||
|
import com.google.gson.*;
|
||||||
|
import ru.gravit.launchserver.auth.handler.AuthHandler;
|
||||||
|
import ru.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class ProtectHandlerAdapter implements JsonSerializer<ProtectHandler>, JsonDeserializer<ProtectHandler> {
|
||||||
|
private static final String PROP_NAME = "type";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProtectHandler deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
|
||||||
|
Class<? extends ProtectHandler> cls = ProtectHandler.getHandlerClass(typename);
|
||||||
|
if(cls == null)
|
||||||
|
{
|
||||||
|
LogHelper.error("ProtectHandler %s not found", typename);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (ProtectHandler) context.deserialize(json, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(ProtectHandler src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
JsonObject jo = context.serialize(src).getAsJsonObject();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
String classPath = ProtectHandler.getHandlerName((Class<ProtectHandler>) src.getClass());
|
||||||
|
jo.add(PROP_NAME, new JsonPrimitive(classPath));
|
||||||
|
|
||||||
|
return jo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,10 +137,12 @@ public void reply() throws Exception {
|
||||||
requestError("Internal auth handler error");
|
requestError("Internal auth handler error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
String protectToken = server.config.protectHandler.generateSecureToken(context);
|
||||||
writeNoError(output);
|
writeNoError(output);
|
||||||
// Write profile and UUID
|
// Write profile and UUID
|
||||||
ProfileByUUIDResponse.getProfile(server, uuid, result.username, client).write(output);
|
ProfileByUUIDResponse.getProfile(server, uuid, result.username, client).write(output);
|
||||||
output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
|
output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
|
||||||
clientData.permissions.write(output);
|
clientData.permissions.write(output);
|
||||||
|
output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,6 +215,7 @@ function doAuth(login, rsaPassword) {
|
||||||
overlay.show(processing.overlay, function (event) {
|
overlay.show(processing.overlay, function (event) {
|
||||||
FunctionalBridge.getHWID.join();
|
FunctionalBridge.getHWID.join();
|
||||||
makeAuthRequest(login, rsaPassword, function (result) {
|
makeAuthRequest(login, rsaPassword, function (result) {
|
||||||
|
FunctionalBridge.setAuthParams(result);
|
||||||
loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions};
|
loginData = { pp: result.playerProfile , accessToken: result.accessToken, permissions: result.permissions};
|
||||||
|
|
||||||
overlay.hide(0, function () {
|
overlay.hide(0, function () {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import ru.gravit.launcher.HWID;
|
import ru.gravit.launcher.HWID;
|
||||||
import ru.gravit.launcher.LauncherAPI;
|
import ru.gravit.launcher.LauncherAPI;
|
||||||
|
import ru.gravit.launcher.events.request.AuthRequestEvent;
|
||||||
import ru.gravit.launcher.guard.LauncherGuardManager;
|
import ru.gravit.launcher.guard.LauncherGuardManager;
|
||||||
import ru.gravit.launcher.hasher.FileNameMatcher;
|
import ru.gravit.launcher.hasher.FileNameMatcher;
|
||||||
import ru.gravit.launcher.hasher.HashedDir;
|
import ru.gravit.launcher.hasher.HashedDir;
|
||||||
|
@ -103,6 +104,12 @@ public static HasherStore getDefaultHasherStore() {
|
||||||
return HasherManager.getDefaultStore();
|
return HasherManager.getDefaultStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public static void setAuthParams(AuthRequestEvent event)
|
||||||
|
{
|
||||||
|
LauncherGuardManager.guard.setProtectToken(event.protectToken);
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface HashedDirRunnable {
|
public interface HashedDirRunnable {
|
||||||
SignedObjectHolder<HashedDir> run() throws Exception;
|
SignedObjectHolder<HashedDir> run() throws Exception;
|
||||||
|
|
|
@ -11,4 +11,5 @@ public interface LauncherGuardInterface {
|
||||||
void init(boolean clientInstance);
|
void init(boolean clientInstance);
|
||||||
void addCustomParams(ClientLauncherContext context);
|
void addCustomParams(ClientLauncherContext context);
|
||||||
void addCustomEnv(ClientLauncherContext context);
|
void addCustomEnv(ClientLauncherContext context);
|
||||||
|
void setProtectToken(String token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,4 +43,9 @@ public void addCustomParams(ClientLauncherContext context) {
|
||||||
public void addCustomEnv(ClientLauncherContext context) {
|
public void addCustomEnv(ClientLauncherContext context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProtectToken(String token) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,4 +40,9 @@ public void addCustomParams(ClientLauncherContext context) {
|
||||||
public void addCustomEnv(ClientLauncherContext context) {
|
public void addCustomEnv(ClientLauncherContext context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProtectToken(String token) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,4 +69,9 @@ public void addCustomEnv(ClientLauncherContext context) {
|
||||||
env.put("GUARD_LICENSE_KEY", config.guardLicenseKey);
|
env.put("GUARD_LICENSE_KEY", config.guardLicenseKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProtectToken(String token) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,8 @@ protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOExce
|
||||||
PlayerProfile pp = new PlayerProfile(input);
|
PlayerProfile pp = new PlayerProfile(input);
|
||||||
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
|
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
|
||||||
ClientPermissions permissions = new ClientPermissions(input);
|
ClientPermissions permissions = new ClientPermissions(input);
|
||||||
return new AuthRequestEvent(pp, accessToken, permissions);
|
String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
|
||||||
|
return new AuthRequestEvent(permissions, pp, accessToken, protectToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,6 +20,8 @@ public AuthRequestEvent() {
|
||||||
public PlayerProfile playerProfile;
|
public PlayerProfile playerProfile;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public String accessToken;
|
public String accessToken;
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public String protectToken;
|
||||||
|
|
||||||
public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) {
|
public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions permissions) {
|
||||||
this.playerProfile = pp;
|
this.playerProfile = pp;
|
||||||
|
@ -27,6 +29,13 @@ public AuthRequestEvent(PlayerProfile pp, String accessToken, ClientPermissions
|
||||||
this.permissions = permissions;
|
this.permissions = permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthRequestEvent(ClientPermissions permissions, PlayerProfile playerProfile, String accessToken, String protectToken) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
this.playerProfile = playerProfile;
|
||||||
|
this.accessToken = accessToken;
|
||||||
|
this.protectToken = protectToken;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
return uuid;
|
return uuid;
|
||||||
|
|
Loading…
Reference in a new issue