Praktik Terbaik Keamanan
Ringkasan
Section titled “Ringkasan”Keamanan sangat penting untuk aplikasi desktop. Ikuti praktik ini untuk menjaga aplikasi Anda tetap aman.
Validasi Input
Section titled “Validasi Input”Selalu Validasi
Section titled “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
Section titled “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
Section titled “Autentikasi”Penyimpanan Password Aman
Section titled “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
Section titled “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
Section titled “Perlindungan Data”Enkripsi Data Sensitif
Section titled “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
Section titled “Penyimpanan Aman”// Use OS keychain for sensitive dataimport "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
Section titled “Keamanan Jaringan”Gunakan HTTPS
Section titled “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
Section titled “Verifikasi Sertifikat”import "crypto/tls"
func secureClient() *http.Client { return &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ MinVersion: tls.VersionTLS12, }, }, }}Operasi File
Section titled “Operasi File”Validasi Path
Section titled “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
Section titled “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
Section titled “Praktik Terbaik”✅ Lakukan
Section titled “✅ 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
Section titled “❌ 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
Section titled “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
Section titled “Langkah Selanjutnya”- Architecture - Pola arsitektur aplikasi
- Best Practices - Praktik terbaik bindings