Praktik Terbaik Keamanan

Ringkasan

Keamanan sangat penting untuk aplikasi desktop. Ikuti praktik ini untuk menjaga aplikasi Anda tetap aman.

Validasi Input

Selalu Validasi

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...
}

Sanitasi HTML

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)
}

Autentikasi

Penyimpanan Password Aman

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
}

Manajemen Session

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)
}

Perlindungan Data

Enkripsi Data Sensitif

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
}

Penyimpanan Aman

// 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")
}

Keamanan Jaringan

Gunakan HTTPS

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)
}

Verifikasi Sertifikat

import "crypto/tls"

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

Operasi File

Validasi Path

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)
}

Rate Limiting

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
}

Praktik Terbaik

✅ Lakukan

  • Validasi semua input
  • Gunakan HTTPS untuk panggilan jaringan
  • Enkripsi data sensitif
  • Gunakan password hashing yang aman
  • Implementasikan rate limiting
  • Jaga dependensi tetap diperbarui
  • Log event keamanan
  • Gunakan OS keychain

❌ Jangan

  • Jangan percaya input pengguna
  • Jangan simpan password dalam plain text
  • Jangan hardcode secret
  • Jangan lewati verifikasi sertifikat
  • Jangan ekspos data sensitif di log
  • Jangan gunakan enkripsi lemah
  • Jangan abaikan pembaruan keamanan

Checklist Keamanan

  • Semua input pengguna divalidasi
  • Password di-hash dengan bcrypt
  • Data sensitif dienkripsi
  • HTTPS digunakan untuk semua panggilan jaringan
  • Rate limiting diimplementasikan
  • Path file divalidasi
  • Dependensi diperbarui
  • Logging keamanan diaktifkan
  • Pesan error tidak bocorkan info
  • Kode direview untuk kerentanan

Langkah Selanjutnya

Edit page

Last updated: