Jujur, ada banyak metode dan teknik otentikasi yang dapat Anda pasang ke aplikasi Anda dan itu tergantung pada logika dan persyaratan bisnis aplikasi.
Misalnya Oauth2, LDAP, otentikasi lokal, dll.
Jawaban saya mengasumsikan Anda mencari otentikasi lokal yang berarti Anda mengelola identitas pengguna dalam aplikasi Anda. Server harus mengekspos satu set API eksternal memungkinkan pengguna dan admin Mengelola akun dan bagaimana mereka ingin mengidentifikasi diri mereka ke Server untuk mencapai komunikasi yang dapat dipercaya. Anda akhirnya akan membuat tabel DB yang menyimpan informasi pengguna. tempat kata sandi di-hash untuk tujuan keamanan Lihat Cara menyimpan kata sandi di dalam basis data
mari asumsikan persyaratan aplikasi untuk mengautentikasi pengguna berdasarkan salah satu metode berikut:
otentikasi dasar (nama pengguna, kata sandi):
Metode auth ini tergantung pada kredensial pengguna yang ditetapkan dalam header Otorisasi yang dikodekan dalam base64 dan didefinisikan dalam rfc7617 , pada dasarnya ketika aplikasi menerima pengguna meminta decode otorisasi dan re-hash password untuk membandingkannya dalam DB hash jika cocok dengan yang diautentikasi oleh pengguna, jika tidak kembalikan kode status 401 ke pengguna.
otentikasi berbasis sertifikat:
Metode auth ini bergantung pada Digital Certificate untuk mengidentifikasi pengguna, dan itu dikenal sebagai auth x509, jadi ketika aplikasi menerima permintaan pengguna itu membaca sertifikat klien dan memverifikasinya yang cocok dengan sertifikat CA Root yang disediakan ke APP.
bearer token:
Metode auth ini tergantung pada token Access yang berumur pendek, Token token adalah string samar, biasanya dihasilkan oleh server sebagai respons terhadap permintaan login. jadi ketika aplikasi menerima permintaan pengguna itu membaca otorisasi dan memvalidasi token untuk mengotentikasi pengguna.
Namun, saya akan merekomendasikan go-guardian
untuk pustaka otentikasi yang dilakukannya melalui serangkaian metode otentikasi yang dikenal sebagai strategi. pada dasarnya Go-Guardian tidak me-mount rute atau mengasumsikan skema database tertentu, yang memaksimalkan fleksibilitas dan memungkinkan keputusan dibuat oleh pengembang.
Menyiapkan go-wali authenticator sangat mudah.
Berikut contoh lengkap metode di atas.
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
}
Pemakaian:
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!!
- Otentikasi dengan kredensial pengguna:
curl -k https://127.0.0.1:8080/resource -u stackoverflow:stackoverflow
Resource!!
- Otentikasi dengan sertifikat pengguna:
curl --cert client.pem --key client-key.pem --cacert ca.pem https://127.0.0.1:8080/resource
Resource!!
Anda dapat mengaktifkan beberapa metode otentikasi sekaligus. Anda biasanya harus menggunakan setidaknya dua metode