security

package
v0.4.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: MIT Imports: 15 Imported by: 0

README

Security Package - SQL Escape

本包提供 SQL 参数化查询工具,帮助开发者安全地构造 SQL 查询语句。

背景

SQL 注入是数据库应用中最常见的安全漏洞之一。传统的防御方式包括:

  1. 参数化查询(推荐) - 使用预编译语句和参数绑定
  2. 输入转义 - 正确转义特殊字符

本包提供输入转义工具,类似于 TiDB 的 sqlescape 包。

重要说明

⚠️ 此工具不能阻止所有类型的 SQL 注入攻击!

安全性取决于开发者的正确使用:

  • 建议优先使用数据库的参数化查询(预编译语句)
  • 此工具主要用于动态 SQL 构建场景
  • 开发者仍需确保编写安全的 SQL

API 参考

EscapeSQL(sql string, args ...interface{}) (string, error)

将参数安全地转义并插入到 SQL 字符串中。

格式说明符:

  • %? - 自动类型转换的参数
  • %% - 输出 %
  • %n - 标识符(表名、列名),自动用反引号包裹

示例:

// 基本使用
query, err := EscapeSQL("SELECT * FROM %n WHERE id = %?", "users", 123)
// 结果: "SELECT * FROM `users` WHERE id = 123"

// 多个参数
query, err := EscapeSQL(
    "INSERT INTO %n (name, age) VALUES (%?, %?)",
    "users", "Alice", 30,
)
// 结果: "INSERT INTO `users` (name, age) VALUES ('Alice', 30)"

// 字符串自动转义
query, err := EscapeSQL(
    "SELECT * FROM %n WHERE name = %?",
    "users", "O'Reilly",
)
// 结果: "SELECT * FROM `users` WHERE name = 'O\\'Reilly'"

// NULL 值
query, err := EscapeSQL(
    "SELECT * FROM %n WHERE deleted_at IS %?",
    "users", nil,
)
// 结果: "SELECT * FROM `users` WHERE deleted_at IS NULL"

// 数组类型
query, err := EscapeSQL(
    "SELECT * FROM %n WHERE id IN (%?)",
    "users", []int{1, 2, 3},
)
// 结果: "SELECT * FROM `users` WHERE id IN (1,2,3)"

// 时间类型
query, err := EscapeSQL(
    "SELECT * FROM %n WHERE created_at = %?",
    "logs", time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC),
)
// 结果: "SELECT * FROM `logs` WHERE created_at = '2024-01-15 10:30:00'"
MustEscapeSQL(sql string, args ...interface{}) string

EscapeSQL 的便捷版本,遇到错误会 panic。

适用于参数类型在编译时已知安全的场景。

query := MustEscapeSQL("SELECT * FROM %n WHERE id = %?", "users", 123)
FormatSQL(w io.Writer, sql string, args ...interface{}) error

EscapeSQL 的 Writer 版本,适用于构建复杂 SQL。

var buf strings.Builder

// 构建复杂查询
FormatSQL(&buf, "SELECT * FROM %n WHERE ", "users")
FormatSQL(&buf, "%n = %?", "status", "active")
FormatSQL(&buf, " AND %n > %?", "age", 18)

fmt.Println(buf.String())
// 输出: SELECT * FROM `users` WHERE `status` = 'active' AND `age` > 18
MustFormatSQL(w *strings.Builder, sql string, args ...interface{})

FormatSQL 的便捷版本,使用 strings.Builder,遇到错误会 panic。

var buf strings.Builder
MustFormatSQL(&buf, "SELECT * FROM %n WHERE id = %?", "users", 123)

支持的类型

标识符 (%n)
  • string - 标识符名称(表名、列名等)
参数 (%?)
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • bool - 转换为 1 (true) 或 0 (false)
  • string - 自动转义特殊字符
  • []byte - 二进制数据(以 _binary'...' 格式)
  • time.Time - 时间格式 'YYYY-MM-DD HH:MM:SS.FFFFFF'
  • json.RawMessage - JSON 数据
  • []string, []int, []int64 - 数组类型(逗号分隔)
  • nil - 转换为 NULL

转义规则

字符串和二进制数据会转义以下特殊字符(使用反斜杠):

字符 转义后
\0 \\0
\n \\n
\r \\r
\\ \\\\
' \\'
" \\"
\x1a \\Z

标识符中的反引号会转义为 ` -> ``。

错误处理

EscapeSQLFormatSQL 可能返回以下错误:

  1. 参数不足 - 格式说明符多于提供的参数
  2. 参数过多 - 提供的参数多于格式说明符
  3. 类型错误 - 标识符必须是字符串类型
  4. 不支持的类型 - 参数类型无法转换为 SQL 值

最佳实践

1. 优先使用参数化查询
// ✅ 推荐:使用数据库参数绑定
db.Query("SELECT * FROM users WHERE id = ?", 123)

// ⚠️  可接受:使用 EscapeSQL
query, _ := EscapeSQL("SELECT * FROM %n WHERE id = %?", "users", 123)
db.Exec(query)
2. 仅在动态 SQL 构建时使用此工具
// 适用于表名或列名动态变化的场景
func QueryTable(tableName string, id int) (string, error) {
    return EscapeSQL("SELECT * FROM %n WHERE id = %?", tableName, id)
}
3. 避免直接拼接用户输入
// ❌ 危险:直接拼接
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)

// ✅ 安全:使用 EscapeSQL
query, _ := EscapeSQL("SELECT * FROM %n WHERE name = %?", "users", userInput)

与其他数据库的兼容性

此工具使用 MySQL 的转义规则(与 TiDB 一致):

  • 字符串用单引号包裹
  • 标识符用反引号包裹
  • 使用反斜杠转义特殊字符

其他数据库可能需要不同的转义规则。

性能考虑

  • EscapeSQL 会预分配足够的缓冲区空间
  • FormatSQL 允许流式构建,适合复杂 SQL
  • 避免在循环中重复构建相同的 SQL

参考实现

本包参考了 TiDB 的 sqlescape 实现:

License

同主项目。

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EscapeSQL

func EscapeSQL(sql string, args ...interface{}) (string, error)

EscapeSQL 将参数安全地转义并插入到 SQL 字符串中 使用格式说明符:

%? - 自动类型转换的参数(类似数据库的参数绑定)
%% - 输出 %
%n - 标识符(表名、列名等),自动用反引号包裹

注意:此工具不能阻止所有类型的 SQL 注入。 编写安全 SQL 仍然是开发者的责任。 建议使用参数化查询(预编译语句)来获得最佳安全性。

示例:

query, err := sqlescape.EscapeSQL("SELECT * FROM %n WHERE id = %?", "users", 123)

func FormatSQL

func FormatSQL(w io.Writer, sql string, args ...interface{}) error

FormatSQL 是 EscapeSQL 的 Writer 版本,适用于构建复杂 SQL

func HashPassword

func HashPassword(password string) string

HashPassword 哈希密码

func MustEscapeSQL

func MustEscapeSQL(sql string, args ...interface{}) string

MustEscapeSQL 是 EscapeSQL 的便捷版本,遇到错误会 panic 适用于参数类型在编译时已知安全的场景

func MustFormatSQL

func MustFormatSQL(w *strings.Builder, sql string, args ...interface{})

MustFormatSQL 是 FormatSQL 的便捷版本,适用于 strings.Builder

func VerifyPassword

func VerifyPassword(password, hash string) bool

VerifyPassword 验证密码

Types

type AuditEvent

type AuditEvent struct {
	ID        string                 `json:"id"`
	TraceID   string                 `json:"trace_id,omitempty"`
	Timestamp time.Time              `json:"timestamp"`
	Level     AuditLevel             `json:"level"`
	EventType AuditEventType         `json:"event_type"`
	User      string                 `json:"user"`
	Database  string                 `json:"database"`
	Table     string                 `json:"table"`
	Query     string                 `json:"query"`
	Message   string                 `json:"message"`
	Metadata  map[string]interface{} `json:"metadata"`
	Success   bool                   `json:"success"`
	Duration  int64                  `json:"duration"` // 毫秒
}

AuditEvent 审计事件

type AuditEventType

type AuditEventType string

AuditEventType 审计事件类型

const (
	EventTypeLogin       AuditEventType = "login"
	EventTypeLogout      AuditEventType = "logout"
	EventTypeQuery       AuditEventType = "query"
	EventTypeInsert      AuditEventType = "insert"
	EventTypeUpdate      AuditEventType = "update"
	EventTypeDelete      AuditEventType = "delete"
	EventTypeDDL         AuditEventType = "ddl"
	EventTypePermission  AuditEventType = "permission"
	EventTypeInjection   AuditEventType = "injection"
	EventTypeError       AuditEventType = "error"
	EventTypeAPIRequest  AuditEventType = "api_request"
	EventTypeMCPToolCall AuditEventType = "mcp_tool_call"
)

type AuditLevel

type AuditLevel int

AuditLevel 审计级别

const (
	AuditLevelInfo AuditLevel = iota
	AuditLevelWarning
	AuditLevelError
	AuditLevelCritical
)

type AuditLogEntry

type AuditLogEntry struct {
	Event *AuditEvent
	Error error
}

AuditLogEntry 审计日志条目

type AuditLogger

type AuditLogger struct {
	// contains filtered or unexported fields
}

AuditLogger 审计日志记录器

func NewAuditLogger

func NewAuditLogger(size int) *AuditLogger

NewAuditLogger 创建审计日志记录器

func (*AuditLogger) Export

func (al *AuditLogger) Export() (string, error)

Export 导出审计日志

func (*AuditLogger) GetEvents

func (al *AuditLogger) GetEvents(offset, limit int) []*AuditEvent

GetEvents 获取事件

func (*AuditLogger) GetEventsByLevel

func (al *AuditLogger) GetEventsByLevel(level AuditLevel) []*AuditEvent

GetEventsByLevel 获取指定级别的事件

func (*AuditLogger) GetEventsByTimeRange

func (al *AuditLogger) GetEventsByTimeRange(start, end time.Time) []*AuditEvent

GetEventsByTimeRange 获取时间范围内的事件

func (*AuditLogger) GetEventsByTraceID

func (al *AuditLogger) GetEventsByTraceID(traceID string) []*AuditEvent

GetEventsByTraceID 获取指定 TraceID 的事件

func (*AuditLogger) GetEventsByType

func (al *AuditLogger) GetEventsByType(eventType AuditEventType) []*AuditEvent

GetEventsByType 获取指定类型的事件

func (*AuditLogger) GetEventsByUser

func (al *AuditLogger) GetEventsByUser(user string) []*AuditEvent

GetEventsByUser 获取用户的事件

func (*AuditLogger) Log

func (al *AuditLogger) Log(event *AuditEvent)

Log 记录审计事件

func (*AuditLogger) LogAPIRequest

func (al *AuditLogger) LogAPIRequest(traceID, clientName, ip, method, path, sql, database string, duration int64, success bool)

LogAPIRequest 记录 HTTP API 请求

func (*AuditLogger) LogDDL

func (al *AuditLogger) LogDDL(traceID, user, database, query string, duration int64, success bool)

LogDDL 记录DDL操作

func (*AuditLogger) LogDelete

func (al *AuditLogger) LogDelete(traceID, user, database, table string, query string, duration int64, success bool)

LogDelete 记录删除操作

func (*AuditLogger) LogError

func (al *AuditLogger) LogError(traceID, user, database, message string, err error)

LogError 记录错误

func (*AuditLogger) LogInjection

func (al *AuditLogger) LogInjection(traceID, user, ip, query string)

LogInjection 记录SQL注入尝试

func (*AuditLogger) LogInsert

func (al *AuditLogger) LogInsert(traceID, user, database, table string, query string, duration int64, success bool)

LogInsert 记录插入操作

func (*AuditLogger) LogLogin

func (al *AuditLogger) LogLogin(traceID, user, ip string, success bool)

LogLogin 记录登录

func (*AuditLogger) LogLogout

func (al *AuditLogger) LogLogout(traceID, user string)

LogLogout 记录登出

func (*AuditLogger) LogMCPToolCall

func (al *AuditLogger) LogMCPToolCall(traceID, clientName, ip, toolName string, args map[string]interface{}, duration int64, success bool)

LogMCPToolCall 记录 MCP 工具调用

func (*AuditLogger) LogPermission

func (al *AuditLogger) LogPermission(user, action string, metadata map[string]interface{})

LogPermission 记录权限变更

func (*AuditLogger) LogQuery

func (al *AuditLogger) LogQuery(traceID, user, database, query string, duration int64, success bool)

LogQuery 记录查询

func (*AuditLogger) LogUpdate

func (al *AuditLogger) LogUpdate(traceID, user, database, table string, query string, duration int64, success bool)

LogUpdate 记录更新操作

type AuthorizationManager

type AuthorizationManager struct {
	// contains filtered or unexported fields
}

AuthorizationManager 授权管理器

func NewAuthorizationManager

func NewAuthorizationManager() *AuthorizationManager

NewAuthorizationManager 创建授权管理器

func (*AuthorizationManager) ActivateUser

func (am *AuthorizationManager) ActivateUser(username string) error

ActivateUser 激活用户

func (*AuthorizationManager) AssignRole

func (am *AuthorizationManager) AssignRole(username string, role Role) error

AssignRole 分配角色

func (*AuthorizationManager) CreateUser

func (am *AuthorizationManager) CreateUser(username, passwordHash string, roles []Role) error

CreateUser 创建用户

func (*AuthorizationManager) DeactivateUser

func (am *AuthorizationManager) DeactivateUser(username string) error

DeactivateUser 停用用户

func (*AuthorizationManager) DeleteUser

func (am *AuthorizationManager) DeleteUser(username string) error

DeleteUser 删除用户

func (*AuthorizationManager) GetUser

func (am *AuthorizationManager) GetUser(username string) (*User, error)

GetUser 获取用户

func (*AuthorizationManager) GrantPermission

func (am *AuthorizationManager) GrantPermission(username string, permission Permission, table string) error

GrantPermission 授予权限

func (*AuthorizationManager) HasPermission

func (am *AuthorizationManager) HasPermission(username string, permission Permission, table string) bool

HasPermission 检查用户是否有指定权限

func (*AuthorizationManager) ListUsers

func (am *AuthorizationManager) ListUsers() []string

ListUsers 列出所有用户

func (*AuthorizationManager) RemoveRole

func (am *AuthorizationManager) RemoveRole(username string, role Role) error

RemoveRole 移除角色

func (*AuthorizationManager) RevokePermission

func (am *AuthorizationManager) RevokePermission(username string, permission Permission, table string) error

RevokePermission 撤销权限

type Encryptor

type Encryptor struct {
	// contains filtered or unexported fields
}

Encryptor 加密器

func NewEncryptor

func NewEncryptor(password string) (*Encryptor, error)

NewEncryptor 创建加密器

func (*Encryptor) Decrypt

func (e *Encryptor) Decrypt(ciphertext string) (string, error)

Decrypt 解密数据

func (*Encryptor) DecryptField

func (e *Encryptor) DecryptField(fieldName, encryptedValue string) (string, error)

DecryptField 解密字段值

func (*Encryptor) Encrypt

func (e *Encryptor) Encrypt(plaintext string) (string, error)

Encrypt 加密数据

func (*Encryptor) EncryptField

func (e *Encryptor) EncryptField(fieldName, value string) (string, error)

EncryptField 加密字段值

type Permission

type Permission int

Permission 权限类型

const (
	PermissionNone   Permission = 0
	PermissionRead   Permission = 1 << 0 // 1
	PermissionWrite  Permission = 1 << 1 // 2
	PermissionDelete Permission = 1 << 2 // 4
	PermissionCreate Permission = 1 << 3 // 8
	PermissionDrop   Permission = 1 << 4 // 16
	PermissionAlter  Permission = 1 << 5 // 32
	PermissionGrant  Permission = 1 << 6 // 64
	PermissionAll    Permission = 0xFF
)

type Role

type Role string

Role 角色类型

const (
	RoleAdmin     Role = "admin"
	RoleModerator Role = "moderator"
	RoleUser      Role = "user"
	RoleReadOnly  Role = "readonly"
	RoleGuest     Role = "guest"
)

type SensitiveFieldsManager

type SensitiveFieldsManager struct {
	// contains filtered or unexported fields
}

SensitiveFieldsManager 敏感字段管理器

func NewSensitiveFieldsManager

func NewSensitiveFieldsManager(password string, fields []string) (*SensitiveFieldsManager, error)

NewSensitiveFieldsManager 创建敏感字段管理器

func (*SensitiveFieldsManager) AddSensitiveField

func (m *SensitiveFieldsManager) AddSensitiveField(table, field string)

AddSensitiveField 添加敏感字段

func (*SensitiveFieldsManager) DecryptFieldIfSensitive

func (m *SensitiveFieldsManager) DecryptFieldIfSensitive(table, field, value string) (string, error)

DecryptFieldIfSensitive 如果字段敏感则解密

func (*SensitiveFieldsManager) DecryptRecord

func (m *SensitiveFieldsManager) DecryptRecord(table string, record map[string]interface{}) (map[string]interface{}, error)

DecryptRecord 解密记录中的敏感字段

func (*SensitiveFieldsManager) EncryptFieldIfSensitive

func (m *SensitiveFieldsManager) EncryptFieldIfSensitive(table, field, value string) (string, error)

EncryptFieldIfSensitive 如果字段敏感则加密

func (*SensitiveFieldsManager) EncryptRecord

func (m *SensitiveFieldsManager) EncryptRecord(table string, record map[string]interface{}) (map[string]interface{}, error)

EncryptRecord 加密记录中的敏感字段

func (*SensitiveFieldsManager) IsSensitive

func (m *SensitiveFieldsManager) IsSensitive(table, field string) bool

IsSensitive 检查字段是否敏感

func (*SensitiveFieldsManager) RemoveSensitiveField

func (m *SensitiveFieldsManager) RemoveSensitiveField(table, field string)

RemoveSensitiveField 移除敏感字段

type User

type User struct {
	Username     string
	PasswordHash string
	Roles        []Role
	Permissions  map[string]Permission // table -> permission
	CreatedAt    time.Time
	UpdatedAt    time.Time
	IsActive     bool
}

User 用户

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL