fscan/plugins/init.go
ZacharyZcR d981f0100f perf: 优化插件系统性能,消除重复实例化问题
- 添加plugins.Exists()函数,避免不必要的插件实例创建
- 合并PluginInfo数据结构,统一插件工厂和端口信息存储
- 修复Scanner中重复调用plugins.Get()的性能问题
- 优化BaseScanStrategy.pluginExists()实现效率

主要性能改进:
* 消除21×57=1197次不必要的本地插件实例化
* 提升插件存在性检查效率,从O(n)遍历优化为O(1)查找
* 改善数据内聚性,插件元数据集中管理
* 保持所有现有插件控制逻辑和功能完整性

测试验证:
* 无-local参数时不再创建本地插件实例
* 端口匹配、Web检测、互斥验证等功能正常
* 插件注册和执行逻辑保持向后兼容
2025-08-26 19:53:57 +08:00

151 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package plugins
import (
"context"
"strings"
"sync"
"github.com/shadow1ng/fscan/common"
)
// Plugin 统一插件接口 - 消除过度设计
//
// Linus哲学"好代码没有特殊情况"
// 之前3个不同的接口做同样的事情
// 现在1个接口统治所有插件
type Plugin interface {
Name() string
Scan(ctx context.Context, info *common.HostInfo) *Result
}
// Result 统一结果结构 - 合并所有类型
type Result struct {
Success bool
Service string
Username string
Password string
Banner string
Output string // web/local插件使用
Error error
// Web插件字段
Title string // 网页标题
Status int // HTTP状态码
Server string // 服务器信息
Length int // 响应长度
VulInfo string // 漏洞信息
}
// Exploiter 利用接口 - 保持向后兼容
type Exploiter interface {
Exploit(ctx context.Context, info *common.HostInfo, creds Credential) *ExploitResult
}
// ExploitResult 利用结果
type ExploitResult struct {
Success bool
Output string
Error error
}
// Credential 认证凭据
type Credential struct {
Username string
Password string
KeyData []byte
}
// PluginInfo 插件信息结构 - 合并工厂和端口信息
type PluginInfo struct {
factory func() Plugin
ports []int
}
// 全局插件注册表 - 一个数据结构解决所有问题
var (
plugins = make(map[string]*PluginInfo)
mutex sync.RWMutex
)
// Register 注册插件 - 一个函数统治所有注册
func Register(name string, factory func() Plugin) {
RegisterWithPorts(name, factory, []int{})
}
// RegisterWithPorts 注册带端口信息的插件
func RegisterWithPorts(name string, factory func() Plugin, ports []int) {
mutex.Lock()
defer mutex.Unlock()
plugins[name] = &PluginInfo{
factory: factory,
ports: ports,
}
}
// Get 获取插件实例
func Get(name string) Plugin {
mutex.RLock()
defer mutex.RUnlock()
if info, exists := plugins[name]; exists {
return info.factory()
}
return nil
}
// All 获取所有插件名称
func All() []string {
mutex.RLock()
defer mutex.RUnlock()
names := make([]string, 0, len(plugins))
for name := range plugins {
names = append(names, name)
}
return names
}
// Exists 检查插件是否存在,不创建实例 - 解决性能问题
func Exists(name string) bool {
mutex.RLock()
defer mutex.RUnlock()
_, exists := plugins[name]
return exists
}
// GetPluginPorts 获取插件端口列表
func GetPluginPorts(name string) []int {
mutex.RLock()
defer mutex.RUnlock()
if info, exists := plugins[name]; exists {
return info.ports
}
return []int{} // 返回空列表表示适用于所有端口
}
// GenerateCredentials 生成测试凭据 - 从services包移到这里统一管理
func GenerateCredentials(service string) []Credential {
users := common.Userdict[service]
if len(users) == 0 {
users = []string{"admin", "root", "administrator", "user", "guest", ""}
}
passwords := common.Passwords
if len(passwords) == 0 {
passwords = []string{"", "admin", "root", "password", "123456"}
}
var credentials []Credential
for _, user := range users {
for _, pass := range passwords {
actualPass := strings.Replace(pass, "{user}", user, -1)
credentials = append(credentials, Credential{
Username: user,
Password: actualPass,
})
}
}
return credentials
}