forked from boyska/feedpanel
76 lines
1.4 KiB
Go
76 lines
1.4 KiB
Go
package panelui
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
)
|
|
|
|
type ctxKey int
|
|
|
|
const (
|
|
keyUser = iota
|
|
)
|
|
|
|
//HeaderAuth is a Negroni-compatible Middleware
|
|
type HeaderAuth struct {
|
|
AllowedNames []string
|
|
AllowedIPs []net.IP
|
|
RequireUser bool
|
|
}
|
|
|
|
func _getSourceIP(req *http.Request) (net.IP, error) {
|
|
ip, _, err := net.SplitHostPort(req.RemoteAddr)
|
|
if err != nil {
|
|
return net.IP{}, err
|
|
}
|
|
|
|
userIP := net.ParseIP(ip)
|
|
if userIP == nil {
|
|
return net.IP{}, err
|
|
}
|
|
return userIP, nil
|
|
}
|
|
|
|
func (ha HeaderAuth) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
|
srcIP, err := _getSourceIP(r)
|
|
if err != nil {
|
|
rw.WriteHeader(501)
|
|
return
|
|
}
|
|
found := false
|
|
if len(ha.AllowedNames) == 0 && len(ha.AllowedIPs) == 0 {
|
|
found = true
|
|
}
|
|
if !found && len(ha.AllowedIPs) > 0 {
|
|
for _, allowedIP := range ha.AllowedIPs {
|
|
if allowedIP.Equal(srcIP) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !found && len(ha.AllowedNames) > 0 {
|
|
for _, name := range ha.AllowedNames {
|
|
nameips, err := net.LookupIP(name)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
for _, allowedIP := range nameips {
|
|
if allowedIP.Equal(srcIP) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
user := r.Header.Get("X-Forwarded-User")
|
|
if !found || (ha.RequireUser && user == "") {
|
|
rw.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
ctx := r.Context()
|
|
ctx = context.WithValue(ctx, keyUser, user)
|
|
next(rw, r.WithContext(ctx))
|
|
return
|
|
}
|