mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-17 23:45:41 -05:00
caddyauth: Use singleflight for basic auth (#5344)
* caddyauth: Add singleflight for basic auth * Fixes #5338 * it occurred the thunder herd problem like this https://medium.com/@mhrlife/avoid-duplicate-requests-while-filling-cache-98c687879f59 * Update modules/caddyhttp/caddyauth/basicauth.go Fix comment Co-authored-by: Francis Lavoie <lavofr@gmail.com> --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
This commit is contained in:
parent
ac83b7e218
commit
8d3a1b8bcb
2 changed files with 12 additions and 2 deletions
1
go.mod
1
go.mod
|
@ -32,6 +32,7 @@ require (
|
||||||
go.uber.org/zap v1.23.0
|
go.uber.org/zap v1.23.0
|
||||||
golang.org/x/crypto v0.4.0
|
golang.org/x/crypto v0.4.0
|
||||||
golang.org/x/net v0.5.0
|
golang.org/x/net v0.5.0
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
|
||||||
golang.org/x/term v0.4.0
|
golang.org/x/term v0.4.0
|
||||||
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c
|
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/caddyserver/caddy/v2"
|
"github.com/caddyserver/caddy/v2"
|
||||||
|
"golang.org/x/sync/singleflight"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -142,6 +143,7 @@ func (hba *HTTPBasicAuth) Provision(ctx caddy.Context) error {
|
||||||
if hba.HashCache != nil {
|
if hba.HashCache != nil {
|
||||||
hba.HashCache.cache = make(map[string]bool)
|
hba.HashCache.cache = make(map[string]bool)
|
||||||
hba.HashCache.mu = new(sync.RWMutex)
|
hba.HashCache.mu = new(sync.RWMutex)
|
||||||
|
hba.HashCache.g = new(singleflight.Group)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -190,12 +192,18 @@ func (hba HTTPBasicAuth) correctPassword(account Account, plaintextPassword []by
|
||||||
if ok {
|
if ok {
|
||||||
return same, nil
|
return same, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// slow track: do the expensive op, then add it to the cache
|
// slow track: do the expensive op, then add it to the cache
|
||||||
same, err := compare()
|
// but perform it in a singleflight group so that multiple
|
||||||
|
// parallel requests using the same password don't cause a
|
||||||
|
// thundering herd problem by all performing the same hashing
|
||||||
|
// operation before the first one finishes and caches it.
|
||||||
|
v, err, _ := hba.HashCache.g.Do(cacheKey, func() (any, error) {
|
||||||
|
return compare()
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
same = v.(bool)
|
||||||
hba.HashCache.mu.Lock()
|
hba.HashCache.mu.Lock()
|
||||||
if len(hba.HashCache.cache) >= 1000 {
|
if len(hba.HashCache.cache) >= 1000 {
|
||||||
hba.HashCache.makeRoom() // keep cache size under control
|
hba.HashCache.makeRoom() // keep cache size under control
|
||||||
|
@ -223,6 +231,7 @@ func (hba HTTPBasicAuth) promptForCredentials(w http.ResponseWriter, err error)
|
||||||
// compute on every HTTP request.
|
// compute on every HTTP request.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
mu *sync.RWMutex
|
mu *sync.RWMutex
|
||||||
|
g *singleflight.Group
|
||||||
|
|
||||||
// map of concatenated hashed password + plaintext password + salt, to result
|
// map of concatenated hashed password + plaintext password + salt, to result
|
||||||
cache map[string]bool
|
cache map[string]bool
|
||||||
|
|
Loading…
Add table
Reference in a new issue