mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-29 12:16:16 +08:00
basicauth: Store name of authenticated user (#1426)
* Store name of authenticated user in basicauth for use by upstream middleware such as fastcgi and cgi. * Use request context to transfer name of authorized user from basicauth to upstream middleware. Test retrieval of name from context. * Remove development code that was inadvertently left in place * Use keys of type httpserver.CtxKey to access Context values
This commit is contained in:
parent
82cbd7a96b
commit
977a3c3226
|
@ -7,6 +7,7 @@ package basicauth
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
|
@ -60,6 +61,11 @@ func (a BasicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
|
|||
|
||||
// remove credentials from request to avoid leaking upstream
|
||||
r.Header.Del("Authorization")
|
||||
|
||||
// let upstream middleware (e.g. fastcgi and cgi) know about authenticated
|
||||
// user; this replaces the request with a wrapped instance
|
||||
r = r.WithContext(context.WithValue(r.Context(),
|
||||
httpserver.CtxKey("remote_user"), username))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,19 +14,31 @@ import (
|
|||
)
|
||||
|
||||
func TestBasicAuth(t *testing.T) {
|
||||
var i int
|
||||
// This handler is registered for tests in which the only authorized user is
|
||||
// "okuser"
|
||||
upstreamHandler := func(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
remoteUser, _ := r.Context().Value(httpserver.CtxKey("remote_user")).(string)
|
||||
if remoteUser != "okuser" {
|
||||
t.Errorf("Test %d: expecting remote user 'okuser', got '%s'", i, remoteUser)
|
||||
}
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
rw := BasicAuth{
|
||||
Next: httpserver.HandlerFunc(contentHandler),
|
||||
Next: httpserver.HandlerFunc(upstreamHandler),
|
||||
Rules: []Rule{
|
||||
{Username: "okuser", Password: PlainMatcher("okpass"), Resources: []string{"/testing"}},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
type testType struct {
|
||||
from string
|
||||
result int
|
||||
user string
|
||||
password string
|
||||
}{
|
||||
}
|
||||
|
||||
tests := []testType{
|
||||
{"/testing", http.StatusOK, "okuser", "okpass"},
|
||||
{"/testing", http.StatusUnauthorized, "baduser", "okpass"},
|
||||
{"/testing", http.StatusUnauthorized, "okuser", "badpass"},
|
||||
|
@ -37,7 +49,8 @@ func TestBasicAuth(t *testing.T) {
|
|||
{"/testing", http.StatusUnauthorized, "", ""},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
var test testType
|
||||
for i, test = range tests {
|
||||
req, err := http.NewRequest("GET", test.from, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %d: Could not create HTTP request: %v", i, err)
|
||||
|
|
|
@ -220,6 +220,10 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
|
|||
reqURI = origURI
|
||||
}
|
||||
|
||||
// Retrieve name of remote user that was set by some downstream middleware,
|
||||
// possibly basicauth.
|
||||
remoteUser, _ := r.Context().Value(httpserver.CtxKey("remote_user")).(string) // Blank if not set
|
||||
|
||||
// Some variables are unused but cleared explicitly to prevent
|
||||
// the parent environment from interfering.
|
||||
env = map[string]string{
|
||||
|
@ -235,7 +239,7 @@ func (h Handler) buildEnv(r *http.Request, rule Rule, fpath string) (map[string]
|
|||
"REMOTE_HOST": ip, // For speed, remote host lookups disabled
|
||||
"REMOTE_PORT": port,
|
||||
"REMOTE_IDENT": "", // Not used
|
||||
"REMOTE_USER": "", // Not used
|
||||
"REMOTE_USER": remoteUser,
|
||||
"REQUEST_METHOD": r.Method,
|
||||
"SERVER_NAME": h.ServerName,
|
||||
"SERVER_PORT": h.ServerPort,
|
||||
|
|
Loading…
Reference in New Issue
Block a user