36 lines
1.2 KiB
Go
36 lines
1.2 KiB
Go
package http
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"git.sdf.org/jchenry/x"
|
|
)
|
|
|
|
// BasicAuth wraps an HTTP handler with SHA1-hashed basic authentication.
|
|
// The htpasswd map contains username-to-password mappings (passwords are hashed with SHA1).
|
|
// The realm is used in the WWW-Authenticate header for unauthorized responses.
|
|
// Both htpasswd and realm must be non-empty or this function will panic.
|
|
func BasicAuth(h http.Handler, htpasswd map[string]string, realm string) http.HandlerFunc {
|
|
x.Assert(len(htpasswd) > 0, "http.BasicAuth: htpassword cannot be empty")
|
|
x.Assert(len(realm) > 0, "http.BasicAuth: realm cannot be empty")
|
|
rlm := fmt.Sprintf(`Basic realm="%s"`, realm)
|
|
sha1 := func(password string) string {
|
|
s := sha1.New()
|
|
_, _ = s.Write([]byte(password))
|
|
passwordSum := []byte(s.Sum(nil))
|
|
return base64.StdEncoding.EncodeToString(passwordSum)
|
|
}
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
user, pass, _ := r.BasicAuth()
|
|
if pw, ok := htpasswd[user]; !ok || pass != sha1(pw) {
|
|
w.Header().Set("WWW-Authenticate", rlm)
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
h.ServeHTTP(w, r)
|
|
}
|
|
}
|