Thành thật mà nói, có rất nhiều phương pháp và kỹ thuật xác thực mà bạn có thể cài đặt vào ứng dụng của mình và điều đó phụ thuộc vào logic và yêu cầu kinh doanh của ứng dụng.
Ví dụ: Oauth2, LDAP, xác thực cục bộ, v.v ...
Câu trả lời của tôi cho rằng bạn đang tìm kiếm xác thực cục bộ, có nghĩa là bạn quản lý danh tính người dùng trong ứng dụng của mình. Máy chủ phải hiển thị một bộ API bên ngoài cho phép người dùng và quản trị viên Quản lý tài khoản và cách họ muốn nhận dạng chính mình với Máy chủ để đạt được giao tiếp đáng tin cậy. cuối cùng bạn sẽ tạo một bảng DB chứa thông tin của người dùng. nơi mật khẩu được băm cho mục đích bảo mật Xem Cách lưu trữ mật khẩu trong cơ sở dữ liệu
giả sử các yêu cầu ứng dụng để xác thực người dùng dựa trên một trong các phương pháp sau:
xác thực cơ bản (tên người dùng, mật khẩu):
Phương thức xác thực này phụ thuộc vào thông tin xác thực người dùng được đặt trong tiêu đề ủy quyền được mã hóa trong base64 và được xác định trong rfc7617 , về cơ bản khi ứng dụng nhận được yêu cầu người dùng giải mã ủy quyền và băm lại mật khẩu để so sánh nó trong DB băm nếu nó khớp với người dùng được xác thực bằng cách khác trả lại mã trạng thái 401 cho người dùng.
Xác thực dựa trên chứng chỉ:
Phương thức xác thực này phụ thuộc vào Chứng chỉ kỹ thuật số để xác định người dùng và được gọi là x509 auth, vì vậy khi ứng dụng nhận được yêu cầu của người dùng, nó sẽ đọc chứng chỉ của khách hàng và xác minh nó phù hợp với chứng chỉ CA Root được cung cấp đến APP.
Mã thông báo mang:
Phương thức xác thực này phụ thuộc vào mã thông báo truy cập ngắn hạn, Mã thông báo mang là một chuỗi mật mã, thường được tạo bởi máy chủ để đáp ứng yêu cầu đăng nhập. do đó, khi ứng dụng nhận được yêu cầu của người dùng, nó sẽ đọc ủy quyền và xác thực mã thông báo để xác thực người dùng.
Tuy nhiên, tôi khuyên bạn nên đi người giám hộ
cho thư viện xác thực thông qua một bộ phương thức xác thực mở rộng được gọi là chiến lược. về cơ bản, Go-Guardian không gắn kết các tuyến hoặc giả định bất kỳ lược đồ cơ sở dữ liệu cụ thể nào, điều này tối đa hóa tính linh hoạt và cho phép các nhà phát triển đưa ra quyết định.
Thiết lập một trình xác thực người giám hộ đi là đơn giản.
Dưới đây là ví dụ đầy đủ của các phương pháp trên.
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
}
Sử dụng:
curl -k https://127.0.0.1:8080/login -u stackoverflow:stackoverflow
token: 90d64460d14870c08c81352a05dedd3465940a7
- Xác thực bằng mã thông báo:
curl -k https://127.0.0.1:8080/resource -H "Authorization: Bearer 90d64460d14870c08c81352a05dedd3465940a7"
Resource!!
- Xác thực bằng thông tin xác thực người dùng:
curl -k https://127.0.0.1:8080/resource -u stackoverflow:stackoverflow
Resource!!
- Xác thực bằng chứng chỉ người dùng:
curl --cert client.pem --key client-key.pem --cacert ca.pem https://127.0.0.1:8080/resource
Resource!!
Bạn có thể kích hoạt nhiều phương thức xác thực cùng một lúc. Bạn thường nên sử dụng ít nhất hai phương pháp