From 1ffda21ae38d203e381bedbf7bdbbd69c9031062 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Fri, 20 May 2022 14:54:26 -0600 Subject: Implement ratelimit on authentications --- srv/src/http/auth.go | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'srv/src/http/auth.go') diff --git a/srv/src/http/auth.go b/srv/src/http/auth.go index cd247a3..9527cc8 100644 --- a/srv/src/http/auth.go +++ b/srv/src/http/auth.go @@ -1,7 +1,9 @@ package http import ( + "context" "net/http" + "time" "github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil" "golang.org/x/crypto/bcrypt" @@ -19,21 +21,37 @@ func NewPasswordHash(plaintext string) string { // Auther determines who can do what. type Auther interface { - Allowed(username, password string) bool + Allowed(ctx context.Context, username, password string) bool + Close() error } type auther struct { - users map[string]string + users map[string]string + ticker *time.Ticker } // NewAuther initializes and returns an Auther will which allow the given // username and password hash combinations. Password hashes must have been // created using NewPasswordHash. -func NewAuther(users map[string]string) Auther { - return &auther{users: users} +func NewAuther(users map[string]string, ratelimit time.Duration) Auther { + return &auther{ + users: users, + ticker: time.NewTicker(ratelimit), + } +} + +func (a *auther) Close() error { + a.ticker.Stop() + return nil } -func (a *auther) Allowed(username, password string) bool { +func (a *auther) Allowed(ctx context.Context, username, password string) bool { + + select { + case <-ctx.Done(): + return false + case <-a.ticker.C: + } hashedPassword, ok := a.users[username] if !ok { @@ -64,7 +82,7 @@ func authMiddleware(auther Auther, h http.Handler) http.Handler { return } - if !auther.Allowed(username, password) { + if !auther.Allowed(r.Context(), username, password) { respondUnauthorized(rw, r) return } -- cgit v1.2.3