AccountProfileKeyPairManager.java
net.minecraft.client.multiplayer.AccountProfileKeyPairManager
信息
- 全限定名:net.minecraft.client.multiplayer.AccountProfileKeyPairManager
- 类型:public class
- 包:net.minecraft.client.multiplayer
- 源码路径:src/main/java/net/minecraft/client/multiplayer/AccountProfileKeyPairManager.java
- 起始行号:L36
- 实现:ProfileKeyPairManager
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L37 - 说明:
TODO
- 类型:
-
MINIMUM_PROFILE_KEY_REFRESH_INTERVAL- 类型:
Duration - 修饰符:
private static final - 源码定位:
L38 - 说明:
TODO
- 类型:
-
PROFILE_KEY_PAIR_DIR- 类型:
Path - 修饰符:
private static final - 源码定位:
L39 - 说明:
TODO
- 类型:
-
userApiService- 类型:
UserApiService - 修饰符:
private final - 源码定位:
L40 - 说明:
TODO
- 类型:
-
profileKeyPairPath- 类型:
Path - 修饰符:
private final - 源码定位:
L41 - 说明:
TODO
- 类型:
-
keyPair- 类型:
CompletableFuture<Optional<ProfileKeyPair>> - 修饰符:
private - 源码定位:
L42 - 说明:
TODO
- 类型:
-
nextProfileKeyRefreshTime- 类型:
Instant - 修饰符:
private - 源码定位:
L43 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
public AccountProfileKeyPairManager(UserApiService userApiService, UUID profileId, Path gameDirectory) @ L45
- 构造器名:AccountProfileKeyPairManager
- 源码定位:L45
- 修饰符:public
参数:
- userApiService: UserApiService
- profileId: UUID
- gameDirectory: Path
说明:
TODO
方法
下面的方法块按源码顺序生成。
public CompletableFuture<Optional<ProfileKeyPair>> prepareKeyPair() @ L50
- 方法名:prepareKeyPair
- 源码定位:L50
- 返回类型:CompletableFuture<Optional
> - 修饰符:public
参数:
- 无
说明:
TODO
public boolean shouldRefreshKeyPair() @ L57
- 方法名:shouldRefreshKeyPair
- 源码定位:L57
- 返回类型:boolean
- 修饰符:public
参数:
- 无
说明:
TODO
private CompletableFuture<Optional<ProfileKeyPair>> readOrFetchProfileKeyPair(Optional<ProfileKeyPair> cachedKeyPair) @ L64
- 方法名:readOrFetchProfileKeyPair
- 源码定位:L64
- 返回类型:CompletableFuture<Optional
> - 修饰符:private
参数:
- cachedKeyPair: Optional
说明:
TODO
private Optional<ProfileKeyPair> readProfileKeyPair() @ L86
- 方法名:readProfileKeyPair
- 源码定位:L86
- 返回类型:Optional
- 修饰符:private
参数:
- 无
说明:
TODO
private void writeProfileKeyPair(ProfileKeyPair profileKeyPair) @ L104
- 方法名:writeProfileKeyPair
- 源码定位:L104
- 返回类型:void
- 修饰符:private
参数:
- profileKeyPair: ProfileKeyPair
说明:
TODO
private ProfileKeyPair fetchProfileKeyPair(UserApiService userApiService) @ L125
- 方法名:fetchProfileKeyPair
- 源码定位:L125
- 返回类型:ProfileKeyPair
- 修饰符:private
参数:
- userApiService: UserApiService
说明:
TODO
private static ProfilePublicKey.Data parsePublicKey(KeyPairResponse response) @ L137
- 方法名:parsePublicKey
- 源码定位:L137
- 返回类型:ProfilePublicKey.Data
- 修饰符:private static
参数:
- response: KeyPairResponse
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class AccountProfileKeyPairManager implements ProfileKeyPairManager {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Duration MINIMUM_PROFILE_KEY_REFRESH_INTERVAL = Duration.ofHours(1L);
private static final Path PROFILE_KEY_PAIR_DIR = Path.of("profilekeys");
private final UserApiService userApiService;
private final Path profileKeyPairPath;
private CompletableFuture<Optional<ProfileKeyPair>> keyPair = CompletableFuture.completedFuture(Optional.empty());
private Instant nextProfileKeyRefreshTime = Instant.EPOCH;
public AccountProfileKeyPairManager(UserApiService userApiService, UUID profileId, Path gameDirectory) {
this.userApiService = userApiService;
this.profileKeyPairPath = gameDirectory.resolve(PROFILE_KEY_PAIR_DIR).resolve(profileId + ".json");
}
@Override
public CompletableFuture<Optional<ProfileKeyPair>> prepareKeyPair() {
this.nextProfileKeyRefreshTime = Instant.now().plus(MINIMUM_PROFILE_KEY_REFRESH_INTERVAL);
this.keyPair = this.keyPair.thenCompose(this::readOrFetchProfileKeyPair);
return this.keyPair;
}
@Override
public boolean shouldRefreshKeyPair() {
return this.keyPair.isDone() && Instant.now().isAfter(this.nextProfileKeyRefreshTime)
? this.keyPair.join().map(ProfileKeyPair::dueRefresh).orElse(true)
: false;
}
private CompletableFuture<Optional<ProfileKeyPair>> readOrFetchProfileKeyPair(Optional<ProfileKeyPair> cachedKeyPair) {
return CompletableFuture.supplyAsync(() -> {
if (cachedKeyPair.isPresent() && !cachedKeyPair.get().dueRefresh()) {
if (!SharedConstants.IS_RUNNING_IN_IDE) {
this.writeProfileKeyPair(null);
}
return cachedKeyPair;
} else {
try {
ProfileKeyPair fetchedKeyPair = this.fetchProfileKeyPair(this.userApiService);
this.writeProfileKeyPair(fetchedKeyPair);
return Optional.ofNullable(fetchedKeyPair);
} catch (CryptException | MinecraftClientException | IOException var3) {
LOGGER.error("Failed to retrieve profile key pair", (Throwable)var3);
this.writeProfileKeyPair(null);
return cachedKeyPair;
}
}
}, Util.nonCriticalIoPool());
}
private Optional<ProfileKeyPair> readProfileKeyPair() {
if (Files.notExists(this.profileKeyPairPath)) {
return Optional.empty();
} else {
try {
Optional var2;
try (BufferedReader bufferedReader = Files.newBufferedReader(this.profileKeyPairPath)) {
var2 = ProfileKeyPair.CODEC.parse(JsonOps.INSTANCE, StrictJsonParser.parse(bufferedReader)).result();
}
return var2;
} catch (Exception var6) {
LOGGER.error("Failed to read profile key pair file {}", this.profileKeyPairPath, var6);
return Optional.empty();
}
}
}
private void writeProfileKeyPair(@Nullable ProfileKeyPair profileKeyPair) {
try {
Files.deleteIfExists(this.profileKeyPairPath);
} catch (IOException var3) {
LOGGER.error("Failed to delete profile key pair file {}", this.profileKeyPairPath, var3);
}
if (profileKeyPair != null) {
if (SharedConstants.IS_RUNNING_IN_IDE) {
ProfileKeyPair.CODEC.encodeStart(JsonOps.INSTANCE, profileKeyPair).ifSuccess(jsonStr -> {
try {
Files.createDirectories(this.profileKeyPairPath.getParent());
Files.writeString(this.profileKeyPairPath, jsonStr.toString());
} catch (Exception var3x) {
LOGGER.error("Failed to write profile key pair file {}", this.profileKeyPairPath, var3x);
}
});
}
}
}
private @Nullable ProfileKeyPair fetchProfileKeyPair(UserApiService userApiService) throws CryptException, IOException {
KeyPairResponse keyPair = userApiService.getKeyPair();
if (keyPair != null) {
ProfilePublicKey.Data publicKeyData = parsePublicKey(keyPair);
return new ProfileKeyPair(
Crypt.stringToPemRsaPrivateKey(keyPair.keyPair().privateKey()), new ProfilePublicKey(publicKeyData), Instant.parse(keyPair.refreshedAfter())
);
} else {
return null;
}
}
private static ProfilePublicKey.Data parsePublicKey(KeyPairResponse response) throws CryptException {
KeyPair keyPair = response.keyPair();
if (keyPair != null
&& !Strings.isNullOrEmpty(keyPair.publicKey())
&& response.publicKeySignature() != null
&& response.publicKeySignature().array().length != 0) {
try {
Instant expiresAt = Instant.parse(response.expiresAt());
PublicKey key = Crypt.stringToRsaPublicKey(keyPair.publicKey());
ByteBuffer signature = response.publicKeySignature();
return new ProfilePublicKey.Data(expiresAt, key, signature.array());
} catch (IllegalArgumentException | DateTimeException var5) {
throw new CryptException(var5);
}
} else {
throw new CryptException(new MissingException("Missing public key"));
}
}
}引用的其他类
-
- 引用位置:
实现
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Crypt.stringToPemRsaPrivateKey(), Crypt.stringToRsaPublicKey()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
CryptException()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
StrictJsonParser.parse()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Util.nonCriticalIoPool()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用/返回值 - 关联成员:
ProfileKeyPair()
- 引用位置:
-
- 引用位置:
方法调用/构造调用/返回值 - 关联成员:
Data(), ProfilePublicKey(), ProfilePublicKey.Data()
- 引用位置: