mirror of
				https://e.coding.net/circlecloud/Yum.git
				synced 2025-11-04 05:06:02 +00:00 
			
		
		
		
	feat: 添加安全管理工具
This commit is contained in:
		@@ -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 2015年8月21日下午5: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());
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								src/main/java/pw/yumc/Yum/manager/SecurityManager.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/main/java/pw/yumc/Yum/manager/SecurityManager.java
									
									
									
									
									
										Normal 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 2016年3月31日 下午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()));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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: 插件管理系统使用权限!
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user