Внести изменения

Редактировать эту документацию

Переведите документацию или откройте весь проект на своём компьютере.

Ничего не будет опубликовано, пока вы не решите отправить свою работу.

Рекомендации по обеспечению безопасности

Обеспечьте безопасность приложения Wails

Обзор

Безопасность критически важна для настольных приложений. Следуйте этим рекомендациям, чтобы обеспечить безопасность своего приложения.

Проверка входных данных

Всегда проверяйте входные данные

go
func (s *UserService) CreateUser(email, password string) (*User, error) {
    // Validate email
    if !isValidEmail(email) {
        return nil, errors.New("invalid email")
    }
    
    // Validate password strength
    if len(password) < 8 {
        return nil, errors.New("password too short")
    }
    
    // Sanitise input
    email = strings.TrimSpace(email)
    email = html.EscapeString(email)
    
    // Continue...
}

Очищайте HTML

go
import "html"

func (s *Service) SaveComment(text string) error {
    // Escape HTML
    text = html.EscapeString(text)
    
    // Validate length
    if len(text) > 1000 {
        return errors.New("comment too long")
    }
    
    return s.db.Save(text)
}

Аутентификация

Безопасное хранение паролей

go
import "golang.org/x/crypto/bcrypt"

func hashPassword(password string) (string, error) {
    hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(hash), err
}

func verifyPassword(hash, password string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}

Управление сеансами

go
type Session struct {
    UserID    int
    Token     string
    ExpiresAt time.Time
}

func (a *AuthService) CreateSession(userID int) (*Session, error) {
    token := generateSecureToken()
    
    session := &Session{
        UserID:    userID,
        Token:     token,
        ExpiresAt: time.Now().Add(24 * time.Hour),
    }
    
    return session, a.saveSession(session)
}

Защита данных

Шифруйте конфиденциальные данные

go
import "crypto/aes"
import "crypto/cipher"

func encrypt(data []byte, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    
    gcm, err := cipher.NewGCM(block)
    if err != nil {
        return nil, err
    }
    
    nonce := make([]byte, gcm.NonceSize())
    return gcm.Seal(nonce, nonce, data, nil), nil
}

Безопасное хранение

go
// Use OS keychain for sensitive data
import "github.com/zalando/go-keyring"

func saveAPIKey(key string) error {
    return keyring.Set("myapp", "api_key", key)
}

func getAPIKey() (string, error) {
    return keyring.Get("myapp", "api_key")
}

Сетевая безопасность

Используйте HTTPS

go
func makeAPICall(url string) (*Response, error) {
    // Always use HTTPS
    if !strings.HasPrefix(url, "https://") {
        return nil, errors.New("only HTTPS allowed")
    }
    
    return http.Get(url)
}

Проверяйте сертификаты

go
import "crypto/tls"

func secureClient() *http.Client {
    return &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                MinVersion: tls.VersionTLS12,
            },
        },
    }
}

Операции с файлами

Проверяйте пути

go
func readFile(path string) ([]byte, error) {
    // Prevent path traversal
    if strings.Contains(path, "..") {
        return nil, errors.New("invalid path")
    }
    
    // Check file exists in allowed directory
    absPath, err := filepath.Abs(path)
    if err != nil {
        return nil, err
    }
    
    if !strings.HasPrefix(absPath, allowedDir) {
        return nil, errors.New("access denied")
    }
    
    return os.ReadFile(absPath)
}

Ограничение частоты запросов

go
type RateLimiter struct {
    requests map[string][]time.Time
    mu       sync.Mutex
    limit    int
    window   time.Duration
}

func (r *RateLimiter) Allow(key string) bool {
    r.mu.Lock()
    defer r.mu.Unlock()
    
    now := time.Now()
    
    // Clean old requests
    var recent []time.Time
    for _, t := range r.requests[key] {
        if now.Sub(t) < r.window {
            recent = append(recent, t)
        }
    }
    
    if len(recent) >= r.limit {
        return false
    }
    
    r.requests[key] = append(recent, now)
    return true
}

Рекомендации

✅ Делайте

  • Проверяйте все входные данные
  • Используйте HTTPS для сетевых запросов
  • Шифруйте конфиденциальные данные
  • Используйте безопасное хеширование паролей
  • Реализуйте ограничение частоты запросов
  • Своевременно обновляйте зависимости
  • Регистрируйте события безопасности
  • Используйте системные хранилища учётных данных

❌ Не делайте

  • Не доверяйте пользовательскому вводу
  • Не храните пароли в открытом виде
  • Не встраивайте секреты непосредственно в код
  • Не пропускайте проверку сертификатов
  • Не раскрывайте конфиденциальные данные в журналах
  • Не используйте ненадёжное шифрование
  • Не игнорируйте обновления безопасности

Контрольный список безопасности

  • Все пользовательские входные данные проверены
  • Пароли хешируются с помощью bcrypt
  • Конфиденциальные данные зашифрованы
  • Для всех сетевых запросов используется HTTPS
  • Реализовано ограничение частоты запросов
  • Пути к файлам проверены
  • Зависимости обновлены до актуальных версий
  • Включено журналирование событий безопасности
  • Сообщения об ошибках не раскрывают информацию
  • Код проверен на наличие уязвимостей

Дальнейшие действия

Редактировать страницу

Последнее обновление: