نحوه استفاده از سیستم لایسنس کرفت تِک
در ادامه این مطلب مراحل استفاده از سیستم لایسنس کرفت تِک را یاد خواهیم گرفت و همچنین کاربران را وادار به نصب لودر در کنار پلاگین ها میکنیم !
دلیل اینکار واضح است، توسعه دهنده برای زحمات خود ارزش قائل است و طبیعتا به هیچ شرطی اجازه کرک شدن پلاگین خودش رو نمیده، ما در کرفت تِک در تلاشیم تا با نهایت قدرت از کرک جلوگیری کنیم و تا حد ممکن درصد کرک شدن پلاگین هایمان را کم کنیم.
ساختار سیستم لایسنس کرفت تِک چگونه است :
ارسال درخواست
ارسال درخواست توسط پلاگین شما جهت بررسی.
دریافت آیپی
بررسی و تایید آیپی توسط سیستم لایسنس.
تایید لایسنس
تایید لایسنس نهایی با زمان باقی مانده آن.
بازگردانی اطلاعات
بازگردانی اطلاعات لایسنس بررسی شده در لایه های امنیتی.
دریافت و راه اندازی
دریافت پاسخ توسط پلاگین و راه اندازی.
تمامی بررسی و مراحل بالا بعد از رد شدن از مرحله اول یعنی تایید لودر اتفاق خواهد افتاد !
سیستم بررسی لودر به شکل زیر است.
دریافت اطلاعات
دریافت اطلاعات احراز هویت خرید محصول خاص.
ارسال درخواست به سرور
ارسال درخواست به سرور های کرفت تِک.
بررسی اطلاعات هویتی
بررسی اطلاعات ارسال شده و تایید درصورت صحت اطلاعات.
بررسی حساب و محصول خریداری شده
بررسی حساب کاربر برای دریافت لیست محصولات خریداری شده.
شروع راه اندازی
شروع فعالسازی پلاگین در حافظه موقت رم و ارسال برای مرحله لایسنس.
با گذر از 10 مرحله بصورت موفق پلاگین شما در سرور مقصد با موفقیت فعال خواهد شد و درصورت رد یکی از مراحل پلاگین به طور کل از کار خواهد افتاد و در حافظه رم ذخیره نخواهد شد. از این سو تمامی پلاگین ها در لایه اصلی لودر مخفی و محافظت میشوند که درصد کرک هارا بسیار پایین آورده و از کرک های سطح پایین جلوگیری میکند.
بدانید : قبل از این سیستم جدید کرفت تِک صرفا از یک لایه امنیتی استفاده میکرد به منظور بررسی لایسنس که تعدادی سودجو با آمار به دست آمده موفق به کرک 5 درصد پلاگین ها شدند و با ارتقای سیستم جهت جلوگیری درحال حاضر هنوز آماری از کرک به دستمان نرسیده و موفق شده ایم درصد کرک شدن پلاگین هارا پایین بیاوریم.
کد های آماده برای استفاده از سیستم.
package ir.cblock.test;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class Test extends JavaPlugin {
private static final String PLUGIN_NAME = "CTTest";
private static final String API_URL_TEMPLATE = "https://restrict.craft-tech.ir/safe/license?license=%s&plugin_name=%s&server_ip=%s";
private static final String IP_API_URL = "https://files.craft-tech.ir/ip.php";
@Override
public void onEnable() {
if (!Bukkit.getPluginManager().isPluginEnabled("CTLoader")) {
getLogger().severe("CTLoader dependency not found! Disabling plugin.");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
saveDefaultConfig();
FileConfiguration config = getConfig();
String licenseKey = config.getString("license-key", "").trim();
if (licenseKey.isEmpty() || licenseKey.equals("YOUR_LICENSE_KEY")) {
getLogger().warning("Please provide a valid license key in config.yml! Disabling plugin.");
Bukkit.getPluginManager().disablePlugin(this);
return;
}
getLogger().info("Checking license, please wait...");
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
try {
String publicIp = getPublicIp();
boolean isValid = checkLicense(licenseKey, publicIp);
if (isValid) {
getLogger().info("License successfully verified!");
} else {
getLogger().severe("Invalid or expired license! Disabling plugin.");
disablePluginOnMainThread();
}
} catch (Exception e) {
getLogger().severe("Failed to connect to the license server: " + e.getMessage());
disablePluginOnMainThread();
}
});
}
@Override
public void onDisable() {
}
private String getPublicIp() throws Exception {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(IP_API_URL))
.timeout(Duration.ofSeconds(5))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String body = response.body();
Pattern pattern = Pattern.compile("\"ip\"\\s*:\\s*\"([^\"]+)\"");
Matcher matcher = pattern.matcher(body);
if (matcher.find()) {
return matcher.group(1);
}
}
throw new IllegalStateException("Could not parse IP from response");
}
private boolean checkLicense(String licenseKey, String publicIp) throws Exception {
String finalUrl = String.format(API_URL_TEMPLATE, licenseKey, PLUGIN_NAME, publicIp);
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(finalUrl))
.timeout(Duration.ofSeconds(5))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String body = response.body();
Pattern pattern = Pattern.compile("\"status\"\\s*:\\s*\"(valid)\"");
Matcher matcher = pattern.matcher(body);
return matcher.find();
}
return false;
}
private void disablePluginOnMainThread() {
Bukkit.getScheduler().runTask(this, () -> Bukkit.getPluginManager().disablePlugin(this));
}
}name: test
description: $description
prefix: CT-Test
version: '${version}'
main: ir.cblock.test.Test
api-version: '1.20'
load: STARTUP
depend: [CTLoader]
authors: [ _30Block_ ]
website: https://craft-tech.irجلوگیری از خواندن کد و برداشت آن :
همانطور که میدانید کد جاوای سمت راست بسیار کد ساده شده ای هست و قابل خواندن هست توسط کاربرانی که راه آن را میدانند.
ولی چه کنیم که تا حد بیشتری از کرک و باز سازی یا دستکاری کد جلوگیری کنیم ؟
یکی از راه هایی که میتوان با چند کلیک به سادگی ازش استفاده کرد مبهم سازی کد یا به اصطلاح Obfuscate کردن کد هست.
با اینکار کد شما به صورت محتوایی همچون AAAABBBB میشود و غیرقابل خواندن است و دیکد کردن کد بسیار سخت میشود و امکان خواندنش توسط نرم افزار ها هم وجود ندارد پس تا حد زیادی کار را سخت کردیم، ولی نه برای افراد فوق حرفه ای.
بهترین و ساده ترین ابزاری که میتوانیم از آن برای کد های ماینکرافت استفاده کنیم و توسط Maven و Gradle هم پشتیبانی میشود ProGuard است رایگان محبوب و مناسب برای شروع. در نمونه کد سمت راست ما میتوانیم از ProGuard استفاده کنیم. در چه نوع کد هایی نمیتوان مستقیما از ProGuard استفاده کرد ؟
بخش های اصلی به هیچ وجه نباید مبهم شوند مثل کلاس های حساس و یا متد هایی همچون OnEnable در پلاگین.
در کد چگونه از لایسنس استفاده شده است ؟
همانطور که مشاهده میکنید آدرس های زیادی برای استفاده از لایسنس وجود دارد که تمام آنها توضیح داده خواهد شد و لیست آنها به طور کل برای شما قرار خواهد گرفت.
در کد سمت راست به آدرس API سیستم لایسنس درخواستی ارسال میشود که شامل کد لایسنس کاربر، آیپی سرور مجازی کاربر، نام پلاگین میشود.
برای دریافت آیپی عمومی سرور از API مجزا در سرویس های کرفت تِک استفاده شده است و پیشنهاد میشود از همین آدرس و API استفاده نمایید. نام پلاگین شما در API بصورت یک داده ثابت یا Static است به همین دلیل نیازی به تعریف متد های سخت وجود نداره در URL نام پلاگین را ارسال میکنید در اینجا CTTest قرار دارد. کد لایسنس را از کاربر در فایلی با نام config.yml میگیرید و آن را در آدرس فرا میخوانید. سپس این درخواست دقیقا مشابه مراحل توضیح داده شده بالا روند بررسی را طی میکنند و پلاگین را احراز میکنند.
قبل از استفاده از API پلاگین از وجود لودر اطمینان حاصل میکند تا درصورت نبود CTLoader پلاگین به هیچ عنوان راه اندازی نشود این را هم در کد پیاده سازی کرده ایم و هم در کد yml بالا میتوانید مشاهده کنید که با استفاده از عبارت Depend در لیست پیشنیاز ها قرار گرفته که این راه خیلی تاثیری نداره و کاربر با حذف depend از plugin.yml میتواند این سیستم را دور بزند برای همین بهترین راه قرار دادن در کد در کنار plugin.yml هست.
در تصویر بالا ارور هایی که کاربران حین اجرا به آنها بر میخورند را مشاهده میکنید که به شکل زیر هستند و دلایل خود را نیز برای ارور دارند :
[22:07:33] [Server thread/INFO]: [CTLoader] Anti-debug checks passed
[22:07:33] [Server thread/INFO]: [CTLoader] =========================================
[22:07:33] [Server thread/INFO]: [CTLoader] CTLoader v1.8.1 initializing…
[22:07:33] [Server thread/INFO]: [CTLoader] Loader-Host mode: host1
[22:07:33] [Server thread/INFO]: [CTLoader] =========================================
[22:07:33] [Server thread/INFO]: [CT-Test] Enabling test v1.0-SNAPSHOT
[22:07:33] [Server thread/WARN]: [CT-Test] Please provide a valid license key in config.yml! Disabling plugin.
[22:07:33] [Server thread/INFO]: [CT-Test] Disabling test v1.0-SNAPSHOT
[22:14:01] [Server thread/INFO]: [CT-Test] Disabling test v1.0-SNAPSHOT


