L’Autenticazione Base è uno schema di autenticazione semplice integrato nel protocollo HTTP. Sebbene sia una delle forme più semplici di autenticazione, è ancora ampiamente utilizzata, specialmente per API interne o ambienti di sviluppo.
Quando si usa l’Autenticazione Base:
Authorization: Basic base64(username:password)
Prima, definisci il tuo schema di sicurezza per l’Autenticazione Base nel tuo pacchetto di design:
package design
import (
. "goa.design/goa/v3/dsl"
)
// BasicAuth definisce il nostro schema di sicurezza
var BasicAuth = BasicAuthSecurity("basic", func() {
Description("Usa il tuo nome utente e password per accedere all'API")
})
Puoi applicare l’Autenticazione Base a diversi livelli:
// Livello API - si applica a tutti i servizi e metodi
var _ = API("secure_api", func() {
Security(BasicAuth)
})
// Livello Servizio - si applica a tutti i metodi nel servizio
var _ = Service("secure_service", func() {
Security(BasicAuth)
})
// Livello Metodo - si applica solo a questo metodo
Method("secure_method", func() {
Security(BasicAuth)
})
Per i metodi che usano l’Autenticazione Base, devi definire il payload per includere i campi username e password:
Method("login", func() {
Security(BasicAuth)
Payload(func() {
// Queste funzioni DSL speciali sono riconosciute da Goa
Username("username", String, "Nome utente per l'autenticazione")
Password("password", String, "Password per l'autenticazione")
Required("username", "password")
})
Result(String)
HTTP(func() {
POST("/login")
// Response definisce cosa succede dopo l'autenticazione riuscita
Response(StatusOK)
})
})
Quando Goa genera il codice, dovrai implementare un gestore di sicurezza. Ecco un esempio:
// SecurityBasicAuthFunc implementa la logica di autorizzazione per l'Autenticazione Base
func (s *service) BasicAuth(ctx context.Context, user, pass string) (context.Context, error) {
// Implementa qui la tua logica di autenticazione
if user == "admin" && pass == "secret" {
// Autenticazione riuscita
return ctx, nil
}
// Autenticazione fallita
return ctx, basic.Unauthorized("credenziali non valide")
}
Usa Sempre HTTPS L’Autenticazione Base invia le credenziali codificate in base64 (non crittografate). Usa sempre HTTPS per proteggere le credenziali in transito.
Archiviazione Sicura delle Password
Rate Limiting Implementa il rate limiting per prevenire attacchi di forza bruta:
var _ = Service("secure_service", func() {
Security(BasicAuth)
// Aggiungi annotazione di rate limiting
Meta("ratelimit:limit", "60")
Meta("ratelimit:window", "1m")
})
Messaggi di Errore Non rivelare se il nome utente o la password erano errati. Usa messaggi generici:
return ctx, basic.Unauthorized("credenziali non valide")
Logging Logga i tentativi di autenticazione ma mai le password:
func (s *service) BasicAuth(ctx context.Context, user, pass string) (context.Context, error) {
// Bene: Logga solo il nome utente e il risultato
log.Printf("Tentativo di autenticazione per l'utente: %s", user)
// Male: Non fare mai questo
// log.Printf("Tentativo password: %s", pass)
}
Ecco un esempio completo che mostra come implementare l’Autenticazione Base in un servizio Goa:
package design
import (
. "goa.design/goa/v3/dsl"
)
var BasicAuth = BasicAuthSecurity("basic", func() {
Description("Autenticazione base per l'accesso all'API")
})
var _ = API("secure_api", func() {
Title("Esempio API Sicura")
Description("API che dimostra l'Autenticazione Base")
// Applica l'Autenticazione Base a tutti gli endpoint di default
Security(BasicAuth)
})
var _ = Service("secure_service", func() {
Description("Un servizio sicuro che richiede autenticazione")
Method("getData", func() {
Description("Ottieni dati protetti")
// Definisci i requisiti di sicurezza
Security(BasicAuth)
// Definisci il payload (le credenziali saranno aggiunte automaticamente)
Payload(func() {
// Aggiungi qui eventuali campi payload aggiuntivi
Field(1, "query", String, "Query di ricerca")
})
// Definisci il risultato
Result(ArrayOf(String))
// Definisci il trasporto HTTP
HTTP(func() {
GET("/data")
Response(StatusOK)
Response(StatusUnauthorized, func() {
Description("Credenziali non valide")
})
})
})
// Esempio di endpoint pubblico
Method("health", func() {
Description("Endpoint di controllo salute")
NoSecurity()
Result(String)
HTTP(func() {
GET("/health")
})
})
})
Goa genera diversi componenti per l’Autenticazione Base:
Tipi di Sicurezza
Middleware
Documentazione OpenAPI
Se le credenziali non vengono inviate, controlla:
Authorization
Cause comuni:
Security()
mancante nel designPer client basati su browser, assicura una corretta configurazione CORS:
var _ = Service("secure_service", func() {
// Configura CORS per permettere l'header Authorization
HTTP(func() {
Header("Origin")
Header("Authorization")
Options("/")
})
})