Ehrlich gesagt gibt es viele Authentifizierungsmethoden und -techniken, die Sie in Ihre Anwendung einbinden können und die von der Geschäftslogik und den Anforderungen der Anwendungen abhängen.
Zum Beispiel Oauth2, LDAP, lokale Authentifizierung usw.
Meine Antwort geht davon aus, dass Sie nach lokaler Authentifizierung suchen, was bedeutet, dass Sie die Benutzeridentitäten in Ihrer Anwendung verwalten. Der Server muss eine Reihe externer APIs bereitstellen, mit denen Benutzer und Administratoren die Konten verwalten können und wie sie sich gegenüber dem Server identifizieren möchten, um eine vertrauenswürdige Kommunikation zu erreichen. Am Ende erstellen Sie eine DB-Tabelle mit den Benutzerinformationen. wo das Passwort aus Sicherheitsgründen gehasht wird Siehe Speichern des Kennworts in der Datenbank
Nehmen wir App-Anforderungen an, um Benutzer anhand einer der folgenden Methoden zu authentifizieren:
Basisauthentifizierung (Benutzername, Kennwort):
Diese Authentifizierungsmethode hängt von den Benutzeranmeldeinformationen ab, die im Autorisierungsheader festgelegt sind, der in base64 codiert und in rfc7617 definiert ist ist. Wenn die App den Benutzer empfängt, fordert er die Dekodierung der Autorisierung an und das Kennwort erneut, um es innerhalb der Datenbank zu vergleichen Hash, wenn es übereinstimmt, hat der authentifizierte Benutzer andernfalls den 401-Statuscode an den Benutzer zurückgegeben.
Zertifikatsbasierte Authentifizierung:
Diese Authentifizierungsmethode hängt von einem digitalen Zertifikat ab, um einen Benutzer zu identifizieren. Sie wird als x509-Authentifizierung bezeichnet. Wenn die App die Benutzeranforderungen empfängt, liest sie das Zertifikat des Clients und überprüft, ob es mit dem bereitgestellten CA-Stammzertifikat übereinstimmt zur APP.
Bearer-Token:
Diese Authentifizierungsmethode hängt von kurzlebigen Zugriffstoken ab. Das Bearer-Token ist eine kryptische Zeichenfolge, die normalerweise vom Server als Antwort auf eine Anmeldeanforderung generiert wird. Wenn die App die Benutzeranforderungen empfängt, liest sie die Autorisierung und validiert das Token, um den Benutzer zu authentifizieren.
Ich würde jedoch Go-Guardian empfehlen
für die Authentifizierungsbibliothek die über eine erweiterbare Reihe von Authentifizierungsmethoden ausgeführt wird, die als Strategien bezeichnet werden. Grundsätzlich stellt Go-Guardian keine Routen bereit oder nimmt kein bestimmtes Datenbankschema an, was die Flexibilität maximiert und es dem Entwickler ermöglicht, Entscheidungen zu treffen.
Das Einrichten eines Go-Guardian-Authentifikators ist unkompliziert.
Hier das vollständige Beispiel der oben genannten Methoden.
package main
import (
"context"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
"github.com/golang/groupcache/lru"
"github.com/gorilla/mux"
"github.com/shaj13/go-guardian/auth"
"github.com/shaj13/go-guardian/auth/strategies/basic"
"github.com/shaj13/go-guardian/auth/strategies/bearer"
gx509 "github.com/shaj13/go-guardian/auth/strategies/x509"
"github.com/shaj13/go-guardian/store"
)
var authenticator auth.Authenticator
var cache store.Cache
func middleware(next http.Handler) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Executing Auth Middleware")
user, err := authenticator.Authenticate(r)
if err != nil {
code := http.StatusUnauthorized
http.Error(w, http.StatusText(code), code)
return
}
log.Printf("User %s Authenticated\n", user.UserName())
next.ServeHTTP(w, r)
})
}
func Resource(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Resource!!\n"))
}
func Login(w http.ResponseWriter, r *http.Request) {
token := "90d64460d14870c08c81352a05dedd3465940a7"
user := auth.NewDefaultUser("admin", "1", nil, nil)
cache.Store(token, user, r)
body := fmt.Sprintf("token: %s \n", token)
w.Write([]byte(body))
}
func main() {
opts := x509.VerifyOptions{}
opts.KeyUsages = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
opts.Roots = x509.NewCertPool()
// Read Root Ca Certificate
opts.Roots.AddCert(readCertificate("<root-ca>"))
cache = &store.LRU{
lru.New(100),
&sync.Mutex{},
}
// create strategies
x509Strategy := gx509.New(opts)
basicStrategy := basic.New(validateUser, cache)
tokenStrategy := bearer.New(bearer.NoOpAuthenticate, cache)
authenticator = auth.New()
authenticator.EnableStrategy(gx509.StrategyKey, x509Strategy)
authenticator.EnableStrategy(basic.StrategyKey, basicStrategy)
authenticator.EnableStrategy(bearer.CachedStrategyKey, tokenStrategy)
r := mux.NewRouter()
r.HandleFunc("/resource", middleware(http.HandlerFunc(Resource)))
r.HandleFunc("/login", middleware(http.HandlerFunc(Login)))
log.Fatal(http.ListenAndServeTLS(":8080", "<server-cert>", "<server-key>", r))
}
func validateUser(ctx context.Context, r *http.Request, userName, password string) (auth.Info, error) {
// here connect to db or any other service to fetch user and validate it.
if userName == "stackoverflow" && password == "stackoverflow" {
return auth.NewDefaultUser("stackoverflow", "10", nil, nil), nil
}
return nil, fmt.Errorf("Invalid credentials")
}
func readCertificate(file string) *x509.Certificate {
data, err := ioutil.ReadFile(file)
if err != nil {
log.Fatalf("error reading %s: %v", file, err)
}
p, _ := pem.Decode(data)
cert, err := x509.ParseCertificate(p.Bytes)
if err != nil {
log.Fatalf("error parseing certificate %s: %v", file, err)
}
return cert
}
Verwendung:
curl -k https://127.0.0.1:8080/login -u stackoverflow:stackoverflow
token: 90d64460d14870c08c81352a05dedd3465940a7
- Mit einem Token authentifizieren:
curl -k https://127.0.0.1:8080/resource -H "Authorization: Bearer 90d64460d14870c08c81352a05dedd3465940a7"
Resource!!
- Authentifizieren Sie sich mit einem Benutzerausweis:
curl -k https://127.0.0.1:8080/resource -u stackoverflow:stackoverflow
Resource!!
- Mit einem Benutzerzertifikat authentifizieren:
curl --cert client.pem --key client-key.pem --cacert ca.pem https://127.0.0.1:8080/resource
Resource!!
Sie können mehrere Authentifizierungsmethoden gleichzeitig aktivieren. Normalerweise sollten Sie mindestens zwei Methoden anwenden