Güvenlik En İyi Uygulamaları
Web uygulamaları saldırganlar için birincil hedeftir. Kullanıcı girdisi işleyen, veri depolayan veya ters proxy arkasında çalışan bir Gin uygulaması, üretime geçmeden önce bilinçli güvenlik yapılandırmasına ihtiyaç duyar. Bu kılavuz, en önemli savunmaları kapsar ve her birinin Gin ara katmanı ve standart Go kütüphaneleriyle nasıl uygulanacağını gösterir.
CORS yapılandırması
Bölüm başlığı “CORS yapılandırması”Cross-Origin Resource Sharing (CORS), hangi harici alanların API’nize istek yapabileceğini kontrol eder. Yanlış yapılandırılmış CORS, kötü niyetli web sitelerinin kimliği doğrulanmış kullanıcılar adına sunucunuzdan yanıtları okumasına izin verebilir.
İyi test edilmiş bir çözüm için gin-contrib/cors paketini kullanın.
package main
import ( "time"
"github.com/gin-contrib/cors" "github.com/gin-gonic/gin")
func main() { r := gin.Default()
r.Use(cors.New(cors.Config{ AllowOrigins: []string{"https://example.com"}, AllowMethods: []string{"GET", "POST", "PUT", "DELETE"}, AllowHeaders: []string{"Origin", "Content-Type", "Authorization"}, ExposeHeaders: []string{"Content-Length"}, AllowCredentials: true, MaxAge: 12 * time.Hour, }))
r.GET("/api/data", func(c *gin.Context) { c.JSON(200, gin.H{"message": "ok"}) })
r.Run()}CSRF koruması
Bölüm başlığı “CSRF koruması”Cross-Site Request Forgery, kimliği doğrulanmış bir kullanıcının tarayıcısını uygulamanıza istenmeyen istekler göndermeye yönlendirir. Kimlik doğrulama için çerezlere dayanan herhangi bir durum değiştiren uç nokta (POST, PUT, DELETE) CSRF korumasına ihtiyaç duyar.
Token tabanlı koruma eklemek için gin-contrib/csrf ara katmanını kullanın.
package main
import ( "github.com/gin-contrib/csrf" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin")
func main() { r := gin.Default()
store := cookie.NewStore([]byte("session-secret")) r.Use(sessions.Sessions("mysession", store))
r.Use(csrf.Middleware(csrf.Options{ Secret: "csrf-token-secret", ErrorFunc: func(c *gin.Context) { c.String(403, "CSRF token mismatch") c.Abort() }, }))
r.GET("/form", func(c *gin.Context) { token := csrf.GetToken(c) c.JSON(200, gin.H{"csrf_token": token}) })
r.POST("/form", func(c *gin.Context) { c.JSON(200, gin.H{"message": "submitted"}) })
r.Run()}Hız sınırlama
Bölüm başlığı “Hız sınırlama”Hız sınırlama, kötüye kullanımı, kaba kuvvet saldırılarını ve kaynak tükenmesini önler. Ara katman olarak basit bir istemci başına hız sınırlayıcı oluşturmak için standart kütüphanenin golang.org/x/time/rate paketini kullanabilirsiniz.
package main
import ( "net/http" "sync"
"github.com/gin-gonic/gin" "golang.org/x/time/rate")
func RateLimiter() gin.HandlerFunc { type client struct { limiter *rate.Limiter }
var ( mu sync.Mutex clients = make(map[string]*client) )
return func(c *gin.Context) { ip := c.ClientIP()
mu.Lock() if _, exists := clients[ip]; !exists { // Allow 10 requests per second with a burst of 20 clients[ip] = &client{limiter: rate.NewLimiter(10, 20)} } cl := clients[ip] mu.Unlock()
if !cl.limiter.Allow() { c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{ "error": "rate limit exceeded", }) return }
c.Next() }}
func main() { r := gin.Default() r.Use(RateLimiter())
r.GET("/api/resource", func(c *gin.Context) { c.JSON(200, gin.H{"message": "ok"}) })
r.Run()}Girdi doğrulama ve SQL enjeksiyonu önleme
Bölüm başlığı “Girdi doğrulama ve SQL enjeksiyonu önleme”Her zaman Gin’in model bağlamasını struct etiketleriyle kullanarak girdiyi doğrulayın ve bağlayın. Kullanıcı girdisini birleştirerek asla SQL sorguları oluşturmayın.
Struct etiketleriyle girdi doğrulama
Bölüm başlığı “Struct etiketleriyle girdi doğrulama”type CreateUser struct { Username string `json:"username" binding:"required,alphanum,min=3,max=30"` Email string `json:"email" binding:"required,email"` Age int `json:"age" binding:"required,gte=1,lte=130"`}
func createUserHandler(c *gin.Context) { var req CreateUser if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } // req is now validated; proceed safely}Parametreli sorgular kullanın
Bölüm başlığı “Parametreli sorgular kullanın”// DANGEROUS -- SQL injection vulnerabilityrow := db.QueryRow("SELECT id FROM users WHERE username = '" + username + "'")
// SAFE -- parameterized queryrow := db.QueryRow("SELECT id FROM users WHERE username = $1", username)Bu, her veritabanı kütüphanesi için geçerlidir. database/sql, GORM, sqlx veya başka bir ORM kullanın, her zaman parametre yer tutucuları kullanın ve asla dize birleştirme yapmayın.
XSS önleme
Bölüm başlığı “XSS önleme”Cross-Site Scripting (XSS), bir saldırganın diğer kullanıcıların tarayıcılarında çalışan kötü amaçlı betikler enjekte etmesi durumunda gerçekleşir. Buna karşı birden fazla katmanda savunma yapın.
HTML çıktısını kaçışlama
Bölüm başlığı “HTML çıktısını kaçışlama”HTML şablonları işlerken, Go’nun html/template paketi çıktıyı varsayılan olarak kaçışlar. Kullanıcı tarafından sağlanan verileri JSON olarak döndürüyorsanız, Content-Type başlığının doğru ayarlandığından emin olun, böylece tarayıcılar JSON’u HTML olarak yorumlamaz.
// Gin sets Content-Type automatically for JSON responses.// Use c.JSON, not c.String, when returning structured data.c.JSON(200, gin.H{"input": userInput})JSONP koruması için SecureJSON kullanın
Bölüm başlığı “JSONP koruması için SecureJSON kullanın”Gin, JSON ele geçirmesini önlemek için while(1); ekleyen c.SecureJSON sağlar.
c.SecureJSON(200, gin.H{"data": userInput})Gerektiğinde Content-Type’ı açıkça ayarlayın
Bölüm başlığı “Gerektiğinde Content-Type’ı açıkça ayarlayın”// For API endpoints, always return JSONc.Header("Content-Type", "application/json; charset=utf-8")c.Header("X-Content-Type-Options", "nosniff")X-Content-Type-Options: nosniff başlığı, tarayıcıların MIME türü koklamasını önler ve sunucu başka bir şey olarak bildirdiğinde yanıtı HTML olarak yorumlamalarını engeller.
Güvenlik başlıkları ara katmanı
Bölüm başlığı “Güvenlik başlıkları ara katmanı”Güvenlik başlıkları eklemek, en basit ve en etkili sağlamlaştırma adımlarından biridir. Ayrıntılı bir örnek için Güvenlik Başlıkları sayfasına bakın. Aşağıda temel başlıkların hızlı bir özeti bulunmaktadır.
func SecurityHeaders() gin.HandlerFunc { return func(c *gin.Context) { c.Header("X-Frame-Options", "DENY") c.Header("X-Content-Type-Options", "nosniff") c.Header("Strict-Transport-Security", "max-age=31536000; includeSubDomains") c.Header("Content-Security-Policy", "default-src 'self'") c.Header("Referrer-Policy", "strict-origin") c.Header("Permissions-Policy", "geolocation=(), camera=(), microphone=()") c.Next() }}| Başlık | Neyi önler |
|---|---|
X-Frame-Options: DENY | iframe’ler aracılığıyla clickjacking |
X-Content-Type-Options: nosniff | MIME türü koklama saldırıları |
Strict-Transport-Security | Protokol düşürme ve çerez ele geçirme |
Content-Security-Policy | XSS ve veri enjeksiyonu |
Referrer-Policy | Hassas URL parametrelerinin üçüncü taraflara sızması |
Permissions-Policy | Tarayıcı API’lerinin yetkisiz kullanımı (kamera, mikrofon vb.) |
Güvenilir proxy’ler
Bölüm başlığı “Güvenilir proxy’ler”Uygulamanız bir ters proxy veya yük dengeleyici arkasında çalışıyorsa, Gin’e hangi proxy’lere güveneceğini söylemelisiniz. Bu yapılandırma olmadan, saldırganlar IP tabanlı erişim kontrollerini ve hız sınırlamayı atlamak için X-Forwarded-For başlığını taklit edebilir.
// Trust only your known proxy addressesrouter.SetTrustedProxies([]string{"10.0.0.1", "192.168.1.0/24"})Tam açıklama ve yapılandırma seçenekleri için Güvenilir Proxy’ler sayfasına bakın.
HTTPS ve TLS
Bölüm başlığı “HTTPS ve TLS”Tüm üretim Gin uygulamaları trafiği HTTPS üzerinden sunmalıdır. Gin, Let’s Encrypt aracılığıyla otomatik TLS sertifikalarını destekler.
import "github.com/gin-gonic/autotls"
func main() { r := gin.Default() // ... routes ... log.Fatal(autotls.Run(r, "example.com"))}Özel sertifika yöneticileri dahil olmak üzere eksiksiz kurulum talimatları için Let’s Encrypt Desteği sayfasına bakın.