feat: 添加安全管理工具

dev
502647092 2016-03-31 20:31:38 +08:00
parent 776820e4b7
commit d298c2c6a6
8 changed files with 94 additions and 51 deletions

View File

@ -11,8 +11,10 @@ import cn.citycraft.PluginHelper.config.FileConfig;
import cn.citycraft.PluginHelper.utils.VersionChecker;
import pw.yumc.Yum.api.YumAPI;
import pw.yumc.Yum.commands.FileCommand;
import pw.yumc.Yum.commands.NetCommand;
import pw.yumc.Yum.commands.YumCommand;
import pw.yumc.Yum.manager.NetworkManager;
import pw.yumc.Yum.manager.SecurityManager;
/**
* MC
@ -21,7 +23,7 @@ import pw.yumc.Yum.manager.NetworkManager;
* @since 20158215:14:39
*/
public class Yum extends JavaPlugin {
public FileConfig config;
FileConfig config;
NetworkManager netmgr;
@Override
@ -38,7 +40,9 @@ public class Yum extends JavaPlugin {
public void onEnable() {
new YumAPI(this);
new YumCommand(this);
new NetCommand(this);
new FileCommand(this);
new SecurityManager(this);
new VersionChecker(this);
YumAPI.updaterepo(Bukkit.getConsoleSender());
YumAPI.updatecheck(Bukkit.getConsoleSender());

View File

@ -28,7 +28,7 @@ public class FileCommand implements HandlerCommands {
plugin = yum;
dl = YumAPI.getDownload();
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "file");
cmdhandler.setAllCommandOnlyConsole(yum.config.getBoolean("onlyFileCommandConsole", true));
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyFileCommandConsole", true));
cmdhandler.registerCommands(this);
}
@ -131,7 +131,7 @@ public class FileCommand implements HandlerCommands {
sender.sendMessage("§d路径 §e" + file.getAbsolutePath() + " §c是一个文件 请使用file delete!");
return;
}
for (final String name : plugin.config.getStringList("blacklist")) {
for (final String name : plugin.getConfig().getStringList("blacklist")) {
if (file.getAbsolutePath().toLowerCase().endsWith(name)) {
sender.sendMessage("§d路径 §e" + file.getAbsolutePath() + " §c不允许被删除!");
return;

View File

@ -7,9 +7,10 @@ import cn.citycraft.PluginHelper.commands.InvokeSubCommand;
import pw.yumc.Yum.Yum;
public class NetCommand implements HandlerCommands {
public NetCommand(final Yum yum) {
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "net");
cmdhandler.setAllCommandOnlyConsole(yum.config.getBoolean("onlyNetCommandConsole", false));
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyNetCommandConsole", false));
cmdhandler.registerCommands(this);
}

View File

@ -45,7 +45,7 @@ public class YumCommand implements HandlerCommands, Listener {
plugman = YumAPI.getPlugman();
Bukkit.getPluginManager().registerEvents(this, yum);
final InvokeSubCommand cmdhandler = new InvokeSubCommand(yum, "yum");
cmdhandler.setAllCommandOnlyConsole(yum.config.getBoolean("onlyCommandConsole", false));
cmdhandler.setAllCommandOnlyConsole(yum.getConfig().getBoolean("onlyCommandConsole", false));
cmdhandler.registerCommands(this);
}

View File

@ -5,7 +5,6 @@ import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
@ -13,6 +12,7 @@ import org.bukkit.plugin.Plugin;
import cn.citycraft.PluginHelper.config.FileConfig;
import cn.citycraft.PluginHelper.kit.ExceptionKit;
import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.Yum;
/**
@ -24,7 +24,7 @@ import pw.yumc.Yum.Yum;
public class NetworkManager {
public NetworkManager register(final Yum plugin) {
Bukkit.getConsoleSender().sendMessage("§6[§bYum-网络管理§6] §a注入网络管理系统 将托管服务器网络!");
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §a注入网络管理系统 将托管服务器网络!");
ProxySelector.setDefault(new YumProxySelector(ProxySelector.getDefault(), plugin));
return this;
}
@ -41,7 +41,6 @@ public class NetworkManager {
private final boolean allowPrimaryThread;
private final FileConfig config;
private final ProxySelector defaultSelector;
private final HashMap<ClassLoader, Plugin> pluginMap = new HashMap<>();
public YumProxySelector(final ProxySelector defaultSelector, final Yum plugin) {
this.config = plugin.getConfig();
@ -61,19 +60,17 @@ public class NetworkManager {
@Override
public List<Proxy> select(final URI uri) {
if (debug || Bukkit.isPrimaryThread()) {
final Plugin plugin = this.getRequestingPlugin();
final boolean isPrimaryThread = Bukkit.isPrimaryThread();
if (debug || isPrimaryThread) {
final Plugin plugin = PluginKit.getOperatePlugin();
final String urlinfo = uri.toString();
if (!urlinfo.startsWith("socket") && !urlinfo.toLowerCase().contains("yumc") && !urlinfo.toLowerCase().contains("pom.xml")) {
final String str = debug ? "§6[§bYum-网络监控§6] §c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!" : "§6[§bYum-网络管理§6] §c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!";
if (plugin == null) {
Bukkit.getConsoleSender().sendMessage(String.format(str, "未知(请查看堆栈)", urlinfo));
Thread.dumpStack();
} else if (!plugin.getName().equalsIgnoreCase("Yum")) {
if (!urlinfo.startsWith("socket") && !urlinfo.toLowerCase().contains("yumc") && !urlinfo.toLowerCase().contains("pom.xml") && !urlinfo.toLowerCase().contains("502647092")) {
final String str = isPrimaryThread ? "§6[§bYum §a网络管理§6] §c插件 §6%s §c尝试在主线程访问 §e%s §4可能会导致服务器卡顿或无响应!" : "§6[§bYum §a网络监控§6] §c插件 §6%s §c尝试访问 §e%s §c请注意服务器网络安全!";
if (plugin != null) {
Bukkit.getConsoleSender().sendMessage(String.format(str, plugin.getName(), urlinfo));
if (!allowPrimaryThread) {
Bukkit.getConsoleSender().sendMessage("§6[§bYum-网络管理§6] §4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
ExceptionKit.throwException(new IOException("[Yum-网络管理] 已开启网络防护 不允许在主线程访问网络!"));
if (!allowPrimaryThread && isPrimaryThread) {
Bukkit.getConsoleSender().sendMessage("§6[§bYum §a网络管理§6] §4已阻止插件 §b" + plugin.getName() + " §4在主线程访问网络!");
ExceptionKit.throwException(new IOException("[Yum 网络防护] 已开启网络防护 不允许在主线程访问网络!"));
}
}
}
@ -81,32 +78,6 @@ public class NetworkManager {
return defaultSelector.select(uri);
}
private void collectPlugin() {
if (Bukkit.getPluginManager().getPlugins().length != pluginMap.keySet().size() - 1) {
pluginMap.clear();
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
pluginMap.put(plugin.getClass().getClassLoader(), plugin);
}
}
}
private Plugin getRequestingPlugin() {
collectPlugin();
final StackTraceElement[] stacktrace = new Exception().getStackTrace();
for (final StackTraceElement element : stacktrace) {
try {
final ClassLoader loader = Class.forName(element.getClassName(), false, getClass().getClassLoader()).getClassLoader();
if (pluginMap.containsKey(loader)) {
final Plugin p = pluginMap.get(loader);
if (element.getClassName().contains("pw.yumc.Yum.utils.") || !p.getName().equalsIgnoreCase("Yum")) {
return p;
}
}
} catch (final ClassNotFoundException ex) {
}
}
return null;
}
}
}

View File

@ -15,6 +15,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
@ -30,6 +31,7 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.UnknownDependencyException;
import org.bukkit.plugin.java.JavaPluginLoader;
import com.google.common.base.Joiner;
@ -536,8 +538,7 @@ public class PluginsManager {
List<Plugin> plugins = null;
Map<String, Plugin> lookupNames = null;
Map<String, Command> knownCommands = null;
// ###移除类加载器后会导致插件无法载入###
// Map<Pattern, PluginLoader> fileAssociations = null;
final Map<Pattern, JavaPluginLoader> fileAssociations = null;
if (pluginManager == null) {
sender.sendMessage("§4异常: §c插件管理类反射获取失败!");
return false;
@ -558,11 +559,11 @@ public class PluginsManager {
final Field knownCommandsField = commandMap.getClass().getDeclaredField("knownCommands");
knownCommandsField.setAccessible(true);
knownCommands = (Map<String, Command>) knownCommandsField.get(commandMap);
// ###移除类加载器后会导致插件无法载入###
// XXX 暂时用不到
// final Field fileAssociationsField = pluginManager.getClass().getDeclaredField("fileAssociations");
// fileAssociationsField.setAccessible(true);
// fileAssociations = (Map<Pattern, PluginLoader>) fileAssociationsField.get(pluginManager);
// fileAssociations = (Map<Pattern, JavaPluginLoader>) fileAssociationsField.get(pluginManager);
} catch (final Exception e) {
sender.sendMessage("§4异常: §c" + e.getMessage() + " 插件 §b" + name + " §c卸载失败!");
return false;
@ -592,16 +593,39 @@ public class PluginsManager {
}
}
}
// try {
// if (fileAssociations != null) {
// // XXX 不能移除 会导致无法加载
// for (final Iterator<Entry<Pattern, JavaPluginLoader>> filter = fileAssociations.entrySet().iterator(); filter.hasNext();) {
// final Entry<Pattern, JavaPluginLoader> entry = filter.next();
// final Matcher match = entry.getKey().matcher(getPluginFile(next).getName());
// if (match.find()) {
// final JavaPluginLoader pluginLoader = entry.getValue();
// final Field loadersField = pluginLoader.getClass().getDeclaredField("loaders");
// loadersField.setAccessible(true);
// final Map<String, URLClassLoader> loaders = (Map<String, URLClassLoader>) loadersField.get(pluginLoader);
// // XXX 不能移除 会导致无法调用其他插件
// loaders.clear();
// sender.sendMessage("§6卸载: §a移除插件 §b" + name + " §a的类实例缓存!");
// }
// }
// }
// } catch (final Exception e) {
// e.printStackTrace();
// }
sender.sendMessage("§6卸载: §a注销插件 §b" + name + " §a的所有命令!");
final ClassLoader cl = next.getClass().getClassLoader();
try {
((URLClassLoader) cl).close();
} catch (final IOException ex) {
ex.printStackTrace();
}
System.gc();
}
}
if (!pluginVersion.isEmpty()) {
if (!pluginVersion.isEmpty())
{
sender.sendMessage("§6卸载: §a插件 §b" + name + " §a版本 §d" + pluginVersion + " §a已成功卸载!");
return true;
}

View File

@ -0,0 +1,36 @@
package pw.yumc.Yum.manager;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import cn.citycraft.PluginHelper.kit.PluginKit;
import pw.yumc.Yum.Yum;
import pw.yumc.injected.event.SetOpEvent;
/**
*
* @since 2016331 3:01:22
* @author
*/
public class SecurityManager implements Listener {
public String warn = "§6[§bYum §a安全系统§6] §c插件 §e%s §c已设置玩家 §a%s §c为OP §4请注意服务器安全!";
public String prevent = "§6[§bYum §a安全系统§6] §c黑名单插件 §e%s §c尝试设置玩家 §a%s §c为OP §a安全系统已成功拦截!";
public SecurityManager(final Yum yum) {
Bukkit.getPluginManager().registerEvents(this, yum);
}
@EventHandler
public void setop(final SetOpEvent event) {
final Plugin plugin = PluginKit.getOperatePlugin();
if (plugin != null) {
if (plugin.getName().equalsIgnoreCase("BukkitInjectedTools")) {
Bukkit.getConsoleSender().sendMessage(String.format(prevent, plugin, event.getOfflinePlayer().getName()));
} else {
Bukkit.getConsoleSender().sendMessage(String.format(warn, plugin, event.getOfflinePlayer().getName()));
}
}
}
}

View File

@ -2,6 +2,7 @@ name: ${project.artifactId}
description: ${project.description}
main: ${project.groupId}.${project.artifactId}.${project.artifactId}
version: ${project.version}-git-${env.GIT_COMMIT}
load: STARTUP
author: 喵♂呜
website: ${ciManagement.url}
commands:
@ -23,6 +24,12 @@ commands:
usage: §6使用§a/file help§6查看帮助!
permission: file.use
permission-message: §c你没有 <permission> 的权限来执行此命令!
security:
description: MC安全管理命令
aliases: [f]
usage: §6使用§a/security help§6查看帮助!
permission: file.use
permission-message: §c你没有 <permission> 的权限来执行此命令!
permissions:
yum.use:
description: 插件管理系统使用权限!