mirror of
https://github.com/GeyserMC/MCProtocolLib.git
synced 2024-12-04 21:01:02 -05:00
Replace specifying proxy with specifying custom auth service clients.
This commit is contained in:
parent
b3cf3acbb3
commit
6c66d7e27b
6 changed files with 194 additions and 61 deletions
|
@ -2,6 +2,8 @@ package com.github.steveice10.mc.protocol.test;
|
|||
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.auth.exception.request.RequestException;
|
||||
import com.github.steveice10.mc.auth.service.AuthenticationService;
|
||||
import com.github.steveice10.mc.auth.service.SessionService;
|
||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||
import com.github.steveice10.mc.protocol.MinecraftProtocol;
|
||||
import com.github.steveice10.mc.protocol.ServerLoginHandler;
|
||||
|
@ -55,8 +57,11 @@ public class MinecraftProtocolTest {
|
|||
|
||||
public static void main(String[] args) {
|
||||
if(SPAWN_SERVER) {
|
||||
SessionService sessionService = new SessionService();
|
||||
sessionService.setProxy(AUTH_PROXY);
|
||||
|
||||
Server server = new Server(HOST, PORT, MinecraftProtocol.class, new TcpSessionFactory());
|
||||
server.setGlobalFlag(MinecraftConstants.AUTH_PROXY_KEY, AUTH_PROXY);
|
||||
server.setGlobalFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
|
||||
server.setGlobalFlag(MinecraftConstants.VERIFY_USERS_KEY, VERIFY_USERS);
|
||||
server.setGlobalFlag(MinecraftConstants.SERVER_INFO_BUILDER_KEY, new ServerInfoBuilder() {
|
||||
@Override
|
||||
|
@ -81,7 +86,7 @@ public class MinecraftProtocolTest {
|
|||
1,
|
||||
new String[] {"minecraft:world"},
|
||||
getDimensionTag(),
|
||||
"minecraft:overworld",
|
||||
getOverworldTag(),
|
||||
"minecraft:world",
|
||||
100,
|
||||
0,
|
||||
|
@ -156,9 +161,12 @@ public class MinecraftProtocolTest {
|
|||
}
|
||||
|
||||
private static void status() {
|
||||
SessionService sessionService = new SessionService();
|
||||
sessionService.setProxy(AUTH_PROXY);
|
||||
|
||||
MinecraftProtocol protocol = new MinecraftProtocol(SubProtocol.STATUS);
|
||||
Client client = new Client(HOST, PORT, protocol, new TcpSessionFactory(PROXY));
|
||||
client.getSession().setFlag(MinecraftConstants.AUTH_PROXY_KEY, AUTH_PROXY);
|
||||
client.getSession().setFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
|
||||
client.getSession().setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, new ServerInfoHandler() {
|
||||
@Override
|
||||
public void handle(Session session, ServerStatusInfo info) {
|
||||
|
@ -190,8 +198,17 @@ public class MinecraftProtocolTest {
|
|||
private static void login() {
|
||||
MinecraftProtocol protocol = null;
|
||||
if(VERIFY_USERS) {
|
||||
|
||||
try {
|
||||
protocol = new MinecraftProtocol(USERNAME, PASSWORD);
|
||||
AuthenticationService authService = new AuthenticationService();
|
||||
authService.setUsername(USERNAME);
|
||||
authService.setPassword(PASSWORD);
|
||||
authService.setProxy(AUTH_PROXY);
|
||||
authService.login();
|
||||
|
||||
// Can also use "new MinecraftProtocol(USERNAME, PASSWORD)"
|
||||
// if you don't need a proxy or any other customizations.
|
||||
protocol = new MinecraftProtocol(authService);
|
||||
System.out.println("Successfully authenticated user.");
|
||||
} catch(RequestException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -201,8 +218,11 @@ public class MinecraftProtocolTest {
|
|||
protocol = new MinecraftProtocol(USERNAME);
|
||||
}
|
||||
|
||||
SessionService sessionService = new SessionService();
|
||||
sessionService.setProxy(AUTH_PROXY);
|
||||
|
||||
Client client = new Client(HOST, PORT, protocol, new TcpSessionFactory(PROXY));
|
||||
client.getSession().setFlag(MinecraftConstants.AUTH_PROXY_KEY, AUTH_PROXY);
|
||||
client.getSession().setFlag(MinecraftConstants.SESSION_SERVICE_KEY, sessionService);
|
||||
client.getSession().addListener(new SessionAdapter() {
|
||||
@Override
|
||||
public void packetReceived(PacketReceivedEvent event) {
|
||||
|
@ -230,27 +250,28 @@ public class MinecraftProtocolTest {
|
|||
private static CompoundTag getDimensionTag() {
|
||||
CompoundTag tag = new CompoundTag("");
|
||||
ListTag dimensionTag = new ListTag("dimension");
|
||||
CompoundTag overworldTag = new CompoundTag("");
|
||||
overworldTag.put(new StringTag("name", "minecraft:overworld"));
|
||||
overworldTag.put(new ByteTag("natural", (byte) 1));
|
||||
overworldTag.put(new FloatTag("ambient_light", 0f));
|
||||
overworldTag.put(new ByteTag("shrunk", (byte) 0));
|
||||
overworldTag.put(new ByteTag("ultrawarm", (byte) 0));
|
||||
overworldTag.put(new ByteTag("has_ceiling", (byte) 0));
|
||||
overworldTag.put(new ByteTag("has_skylight", (byte) 1));
|
||||
overworldTag.put(new ByteTag("piglin_safe", (byte) 0));
|
||||
overworldTag.put(new ByteTag("natural", (byte) 1));
|
||||
overworldTag.put(new FloatTag("ambient_light", 0));
|
||||
overworldTag.put(new StringTag("infiniburn", "minecraft:infiniburn_overworld"));
|
||||
overworldTag.put(new ByteTag("respawn_anchor_works", (byte) 0));
|
||||
overworldTag.put(new ByteTag("has_skylight", (byte) 1));
|
||||
overworldTag.put(new ByteTag("bed_works", (byte) 1));
|
||||
overworldTag.put(new ByteTag("has_raids", (byte) 1));
|
||||
overworldTag.put(new IntTag("logical_height", 256));
|
||||
overworldTag.put(new ByteTag("shrunk", (byte) 0));
|
||||
overworldTag.put(new ByteTag("ultrawarm", (byte) 0));
|
||||
CompoundTag overworldTag = getOverworldTag();
|
||||
dimensionTag.add(overworldTag);
|
||||
overworldTag.put(tag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
private static CompoundTag getOverworldTag() {
|
||||
CompoundTag overworldTag = new CompoundTag("");
|
||||
overworldTag.put(new StringTag("name", "minecraft:overworld"));
|
||||
overworldTag.put(new ByteTag("piglin_safe", (byte) 0));
|
||||
overworldTag.put(new ByteTag("natural", (byte) 1));
|
||||
overworldTag.put(new FloatTag("ambient_light", 0f));
|
||||
overworldTag.put(new StringTag("infiniburn", "minecraft:infiniburn_overworld"));
|
||||
overworldTag.put(new ByteTag("respawn_anchor_works", (byte) 0));
|
||||
overworldTag.put(new ByteTag("has_skylight", (byte) 1));
|
||||
overworldTag.put(new ByteTag("bed_works", (byte) 1));
|
||||
overworldTag.put(new StringTag("effects", "minecraft:overworld"));
|
||||
overworldTag.put(new ByteTag("has_raids", (byte) 1));
|
||||
overworldTag.put(new IntTag("logical_height", 256));
|
||||
overworldTag.put(new FloatTag("coordinate_scale", 1f));
|
||||
overworldTag.put(new ByteTag("ultrawarm", (byte) 0));
|
||||
overworldTag.put(new ByteTag("has_ceiling", (byte) 0));
|
||||
return overworldTag;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,11 @@ import lombok.NonNull;
|
|||
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.net.Proxy;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* Handles making initial login and status requests for clients.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class ClientListener extends SessionAdapter {
|
||||
private final @NonNull SubProtocol targetSubProtocol;
|
||||
|
@ -56,9 +58,7 @@ public class ClientListener extends SessionAdapter {
|
|||
throw new IllegalStateException("Failed to generate shared key.", e);
|
||||
}
|
||||
|
||||
SessionService sessionService = new SessionService();
|
||||
sessionService.setProxy(event.getSession().getFlag(MinecraftConstants.AUTH_PROXY_KEY, Proxy.NO_PROXY));
|
||||
|
||||
SessionService sessionService = event.getSession().getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService());
|
||||
GameProfile profile = event.getSession().getFlag(MinecraftConstants.PROFILE_KEY);
|
||||
String serverId = sessionService.getServerId(packet.getServerId(), packet.getPublicKey(), key);
|
||||
String accessToken = event.getSession().getFlag(MinecraftConstants.ACCESS_TOKEN_KEY);
|
||||
|
|
|
@ -1,23 +1,80 @@
|
|||
package com.github.steveice10.mc.protocol;
|
||||
|
||||
public class MinecraftConstants {
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.auth.service.SessionService;
|
||||
|
||||
/**
|
||||
* Class containing various constants for Minecraft sessions.
|
||||
*/
|
||||
public final class MinecraftConstants {
|
||||
// General Constants
|
||||
|
||||
/**
|
||||
* Current supported game version.
|
||||
*/
|
||||
public static final String GAME_VERSION = "1.16.2";
|
||||
|
||||
/**
|
||||
* Current supported protocol version.
|
||||
*/
|
||||
public static final int PROTOCOL_VERSION = 751;
|
||||
|
||||
// General Key Constants
|
||||
|
||||
/**
|
||||
* Session flag where the user {@link GameProfile} is stored.
|
||||
*/
|
||||
public static final String PROFILE_KEY = "profile";
|
||||
public static final String AUTH_PROXY_KEY = "auth-proxy";
|
||||
|
||||
/**
|
||||
* Session flag for providing a custom {@link SessionService} instance.
|
||||
*/
|
||||
public static final String SESSION_SERVICE_KEY = "session-service";
|
||||
|
||||
// Client Key Constants
|
||||
|
||||
/**
|
||||
* Session flag where the user's access token is stored. Client only.
|
||||
*/
|
||||
public static final String ACCESS_TOKEN_KEY = "access-token";
|
||||
|
||||
/**
|
||||
* Session flag for providing a custom server info response handler. Client only.
|
||||
*/
|
||||
public static final String SERVER_INFO_HANDLER_KEY = "server-info-handler";
|
||||
|
||||
/**
|
||||
* Session flag for providing a custom ping time response handler. Client only.
|
||||
*/
|
||||
public static final String SERVER_PING_TIME_HANDLER_KEY = "server-ping-time-handler";
|
||||
|
||||
// Server Key Constants
|
||||
|
||||
/**
|
||||
* Session flag for determining whether to verify users. Server only.
|
||||
*/
|
||||
public static final String VERIFY_USERS_KEY = "verify-users";
|
||||
|
||||
/**
|
||||
* Session flag for providing a custom server info response builder. Server only.
|
||||
*/
|
||||
public static final String SERVER_INFO_BUILDER_KEY = "info-builder";
|
||||
|
||||
/**
|
||||
* Session flag for providing a custom server login handler. Server only.
|
||||
*/
|
||||
public static final String SERVER_LOGIN_HANDLER_KEY = "login-handler";
|
||||
|
||||
/**
|
||||
* Session flag for storing the current ping time. Server only.
|
||||
*/
|
||||
public static final String PING_KEY = "ping";
|
||||
|
||||
/**
|
||||
* Session flag for determining the packet compression threshold. Server only.
|
||||
*/
|
||||
public static final String SERVER_COMPRESSION_THRESHOLD = "compression-threshold";
|
||||
|
||||
private MinecraftConstants() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,6 +175,9 @@ import java.security.GeneralSecurityException;
|
|||
import java.security.Key;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implements the Minecraft protocol.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class MinecraftProtocol extends PacketProtocol {
|
||||
private SubProtocol subProtocol = SubProtocol.HANDSHAKE;
|
||||
|
@ -182,17 +185,36 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
private AESEncryption encryption = null;
|
||||
|
||||
private SubProtocol targetSubProtocol;
|
||||
|
||||
/**
|
||||
* The player's identity.
|
||||
*/
|
||||
@Getter
|
||||
private GameProfile profile = null;
|
||||
|
||||
/**
|
||||
* Authentication client token.
|
||||
*/
|
||||
@Getter
|
||||
private String clientToken = "";
|
||||
|
||||
/**
|
||||
* Authentication access token.
|
||||
*/
|
||||
@Getter
|
||||
private String accessToken = "";
|
||||
|
||||
/**
|
||||
* Whether to add the default client and server listeners for performing initial login.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean useDefaultListeners = true;
|
||||
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol instance, starting with a specific {@link SubProtocol}.
|
||||
* @param subProtocol {@link SubProtocol} to start with.
|
||||
*/
|
||||
public MinecraftProtocol(SubProtocol subProtocol) {
|
||||
if(subProtocol != SubProtocol.LOGIN && subProtocol != SubProtocol.STATUS) {
|
||||
throw new IllegalArgumentException("Only login and status modes are permitted.");
|
||||
|
@ -204,46 +226,51 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol instance, adopting the given username.
|
||||
* @param username Username to adopt.
|
||||
*/
|
||||
public MinecraftProtocol(String username) {
|
||||
this(SubProtocol.LOGIN);
|
||||
|
||||
this.profile = new GameProfile((UUID) null, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol instance, logging in with the given password credentials.
|
||||
* @param username Username to log in as. Must be the same as when the access token was generated.
|
||||
* @param password Password to log in with.
|
||||
* @throws RequestException If the log in request fails.
|
||||
*/
|
||||
public MinecraftProtocol(String username, String password) throws RequestException {
|
||||
this(username, password, Proxy.NO_PROXY);
|
||||
this(createAuthServiceForPasswordLogin(username, password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol instance, logging in with the given token credentials.
|
||||
* @param username Username to log in as. Must be the same as when the access token was generated.
|
||||
* @param clientToken Client token to log in as. Must be the same as when the access token was generated.
|
||||
* @param accessToken Access token to log in with.
|
||||
* @throws RequestException If the log in request fails.
|
||||
*/
|
||||
public MinecraftProtocol(String username, String clientToken, String accessToken) throws RequestException {
|
||||
this(username, clientToken, accessToken, Proxy.NO_PROXY);
|
||||
this(createAuthServiceForTokenLogin(username, clientToken, accessToken));
|
||||
}
|
||||
|
||||
public MinecraftProtocol(String username, String password, Proxy proxy) throws RequestException {
|
||||
this(username, UUID.randomUUID().toString(), password, false, proxy);
|
||||
}
|
||||
|
||||
public MinecraftProtocol(String username, String clientToken, String accessToken, Proxy proxy) throws RequestException {
|
||||
this(username, clientToken, accessToken, true, proxy);
|
||||
}
|
||||
|
||||
private MinecraftProtocol(String username, String clientToken, String using, boolean token, Proxy authProxy) throws RequestException {
|
||||
this(SubProtocol.LOGIN);
|
||||
|
||||
AuthenticationService auth = new AuthenticationService(clientToken);
|
||||
auth.setProxy(authProxy);
|
||||
auth.setUsername(username);
|
||||
if(token) {
|
||||
auth.setAccessToken(using);
|
||||
} else {
|
||||
auth.setPassword(using);
|
||||
}
|
||||
|
||||
auth.login();
|
||||
this.profile = auth.getSelectedProfile();
|
||||
this.clientToken = auth.getClientToken();
|
||||
this.accessToken = auth.getAccessToken();
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol instance, copying authentication information
|
||||
* from a logged-in {@link AuthenticationService}.
|
||||
* @param authService {@link AuthenticationService} to copy from.
|
||||
*/
|
||||
public MinecraftProtocol(AuthenticationService authService) {
|
||||
this(authService.getSelectedProfile(), authService.getClientToken(), authService.getAccessToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new MinecraftProtocol from authentication information.
|
||||
* @param profile GameProfile to use.
|
||||
* @param clientToken Client token to use.
|
||||
* @param accessToken Access token to use.
|
||||
*/
|
||||
public MinecraftProtocol(GameProfile profile, String clientToken, String accessToken) {
|
||||
this(SubProtocol.LOGIN);
|
||||
this.profile = profile;
|
||||
|
@ -251,6 +278,22 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
private static AuthenticationService createAuthServiceForPasswordLogin(String username, String password) throws RequestException {
|
||||
AuthenticationService auth = new AuthenticationService(UUID.randomUUID().toString());
|
||||
auth.setUsername(username);
|
||||
auth.setPassword(password);
|
||||
auth.login();
|
||||
return auth;
|
||||
}
|
||||
|
||||
private static AuthenticationService createAuthServiceForTokenLogin(String username, String clientToken, String accessToken) throws RequestException {
|
||||
AuthenticationService auth = new AuthenticationService(clientToken);
|
||||
auth.setUsername(username);
|
||||
auth.setAccessToken(accessToken);
|
||||
auth.login();
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSRVRecordPrefix() {
|
||||
return "_minecraft";
|
||||
|
@ -297,6 +340,10 @@ public class MinecraftProtocol extends PacketProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current {@link SubProtocol} the client is in.
|
||||
* @return The current {@link SubProtocol}.
|
||||
*/
|
||||
public SubProtocol getSubProtocol() {
|
||||
return this.subProtocol;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import com.github.steveice10.packetlib.event.session.PacketSentEvent;
|
|||
import com.github.steveice10.packetlib.event.session.SessionAdapter;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.net.Proxy;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -40,6 +39,9 @@ import java.util.Arrays;
|
|||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Handles initial login and status requests for servers.
|
||||
*/
|
||||
public class ServerListener extends SessionAdapter {
|
||||
private static final int DEFAULT_COMPRESSION_THRESHOLD = 256;
|
||||
|
||||
|
@ -190,9 +192,7 @@ public class ServerListener extends SessionAdapter {
|
|||
public void run() {
|
||||
GameProfile profile = null;
|
||||
if(this.key != null) {
|
||||
SessionService sessionService = new SessionService();
|
||||
sessionService.setProxy(this.session.getFlag(MinecraftConstants.AUTH_PROXY_KEY, Proxy.NO_PROXY));
|
||||
|
||||
SessionService sessionService = this.session.getFlag(MinecraftConstants.SESSION_SERVICE_KEY, new SessionService());
|
||||
try {
|
||||
profile = sessionService.getProfileByServer(username, sessionService.getServerId(SERVER_ID, KEY_PAIR.getPublic(), this.key));
|
||||
} catch(RequestException e) {
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
package com.github.steveice10.mc.protocol;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.SubProtocol;
|
||||
import com.github.steveice10.packetlib.Session;
|
||||
|
||||
/**
|
||||
* Interface for handling a session logging in to a server.
|
||||
*/
|
||||
public interface ServerLoginHandler {
|
||||
/**
|
||||
* Called when a session completes the initial login process and is now in the {@link SubProtocol}.GAME.
|
||||
* @param session Session that logged in.
|
||||
*/
|
||||
public void loggedIn(Session session);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue