Чесно кажучи, існує багато методів та методів аутентифікації, які можна встановити у вашу програму, і це залежить від логіки та вимог бізнесу.
Наприклад, Oauth2, LDAP, локальна автентифікація тощо.
Моя відповідь передбачає, що ви шукаєте локальну автентифікацію, що означає, що ви керуєте особами користувача у вашій програмі. Сервер повинен відкривати набір зовнішніх API, що дозволяє користувачам і адміністраторам Керувати обліковими записами та як вони хочуть ідентифікувати себе на Сервері для досягнення надійного зв'язку. ви в кінцевому підсумку створите таблицю БД, що містить інформацію про користувача. де пароль хешований з метою безпеки Див Як зберігати пароль у базі даних
дозвольте припустити вимоги програми для автентифікації користувачів на основі одного з таких методів:
основна автентифікація (ім'я користувача, пароль):
Цей метод автентифікації залежить від наборів даних користувачів у заголовку авторизації, закодованого в base64 та визначеному в rfc7617 , в основному, коли додаток отримує, користувач запитує його декодує авторизацію та повторно хеш-пароль для порівняння його в БД хеш, якщо він відповідний користувачеві, інакше повертає 401 код статусу користувачеві.
аутентифікація на основі сертифікатів:
Цей метод автентифікації залежить від цифрового сертифіката для ідентифікації користувача, і він відомий як x509 auth, тому коли програма отримує запит від користувача, вона зчитує сертифікат клієнта і перевіряє, чи відповідає сертифікат кореневого сертифіката CA, що надається до APP.
маркер носія:
Цей метод автентифікації залежить від короткотривалих маркерів доступу, маркер носія - це криптований рядок, який зазвичай генерується сервером у відповідь на запит на вхід. тому, коли додаток отримує запит користувача, воно зчитує авторизацію та перевіряє маркер для автентифікації користувача.
Однак я б рекомендував go-guardian
для бібліотеки аутентифікації, яку він робить через розширюваний набір методів аутентифікації, відомих як стратегії. в основному Go-Guardian не монтує маршрути і не передбачає будь-якої конкретної схеми бази даних, що забезпечує максимальну гнучкість і дозволяє розробникам приймати рішення.
Налаштування автентифікатора Go-Guard є простим.
Ось повний приклад перерахованих вище методів.
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
}
Використання:
curl -k https://127.0.0.1:8080/login -u stackoverflow:stackoverflow
token: 90d64460d14870c08c81352a05dedd3465940a7
- Аутентифікувати за допомогою маркера:
curl -k https://127.0.0.1:8080/resource -H "Authorization: Bearer 90d64460d14870c08c81352a05dedd3465940a7"
Resource!!
- Аутентифікація за допомогою облікових даних користувача:
curl -k https://127.0.0.1:8080/resource -u stackoverflow:stackoverflow
Resource!!
- Аутентифікат із сертифікатом користувача:
curl --cert client.pem --key client-key.pem --cacert ca.pem https://127.0.0.1:8080/resource
Resource!!
Ви можете ввімкнути відразу кілька методів аутентифікації. Зазвичай слід використовувати як мінімум два методи