Merge pull request #1475 from micro/auth-resolver
Auth integrate resolver to support micro web & api
This commit is contained in:
commit
0f570d98e1
@ -2,7 +2,6 @@
|
|||||||
package path
|
package path
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -13,7 +12,7 @@ type Resolver struct{}
|
|||||||
|
|
||||||
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
func (r *Resolver) Resolve(req *http.Request) (*resolver.Endpoint, error) {
|
||||||
if req.URL.Path == "/" {
|
if req.URL.Path == "/" {
|
||||||
return nil, errors.New("unknown name")
|
return nil, resolver.ErrNotFound
|
||||||
}
|
}
|
||||||
parts := strings.Split(req.URL.Path[1:], "/")
|
parts := strings.Split(req.URL.Path[1:], "/")
|
||||||
return &resolver.Endpoint{
|
return &resolver.Endpoint{
|
||||||
|
@ -2,9 +2,15 @@
|
|||||||
package resolver
|
package resolver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrNotFound = errors.New("not found")
|
||||||
|
ErrInvalidPath = errors.New("invalid path")
|
||||||
|
)
|
||||||
|
|
||||||
// Resolver resolves requests to endpoints
|
// Resolver resolves requests to endpoints
|
||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
Resolve(r *http.Request) (*Endpoint, error)
|
Resolve(r *http.Request) (*Endpoint, error)
|
||||||
|
@ -7,21 +7,34 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/micro/go-micro/v2/api/resolver"
|
||||||
|
"github.com/micro/go-micro/v2/api/resolver/path"
|
||||||
"github.com/micro/go-micro/v2/auth"
|
"github.com/micro/go-micro/v2/auth"
|
||||||
"github.com/micro/go-micro/v2/logger"
|
"github.com/micro/go-micro/v2/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CombinedAuthHandler wraps a server and authenticates requests
|
// CombinedAuthHandler wraps a server and authenticates requests
|
||||||
func CombinedAuthHandler(h http.Handler) http.Handler {
|
func CombinedAuthHandler(namespace string, r resolver.Resolver, h http.Handler) http.Handler {
|
||||||
|
if r == nil {
|
||||||
|
r = path.NewResolver()
|
||||||
|
}
|
||||||
|
if len(namespace) == 0 {
|
||||||
|
namespace = "go.micro"
|
||||||
|
}
|
||||||
|
|
||||||
return authHandler{
|
return authHandler{
|
||||||
handler: h,
|
handler: h,
|
||||||
auth: auth.DefaultAuth,
|
resolver: r,
|
||||||
|
auth: auth.DefaultAuth,
|
||||||
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type authHandler struct {
|
type authHandler struct {
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
auth auth.Auth
|
auth auth.Auth
|
||||||
|
resolver resolver.Resolver
|
||||||
|
namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
@ -65,17 +78,35 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine the name of the service being requested
|
||||||
|
endpoint, err := h.resolver.Resolve(req)
|
||||||
|
if err == resolver.ErrInvalidPath || err == resolver.ErrNotFound {
|
||||||
|
// a file not served by the resolver has been requested (e.g. favicon.ico)
|
||||||
|
endpoint = &resolver.Endpoint{Path: req.URL.Path}
|
||||||
|
} else if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct the resource name, e.g. home => go.micro.web.home
|
||||||
|
resName := h.namespace
|
||||||
|
if len(endpoint.Name) > 0 {
|
||||||
|
resName = resName + "." + endpoint.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine the resource path. there is an inconsistency in how resolvers
|
||||||
|
// use method, some use it as Users.ReadUser (the rpc method), and others
|
||||||
|
// use it as the HTTP method, e.g GET. TODO: Refactor this to make it consistent.
|
||||||
|
resEndpoint := endpoint.Path
|
||||||
|
if len(endpoint.Path) == 0 {
|
||||||
|
resEndpoint = endpoint.Method
|
||||||
|
}
|
||||||
|
|
||||||
// Perform the verification check to see if the account has access to
|
// Perform the verification check to see if the account has access to
|
||||||
// the resource they're requesting
|
// the resource they're requesting
|
||||||
err = h.auth.Verify(acc, &auth.Resource{
|
res := &auth.Resource{Type: "service", Name: resName, Endpoint: resEndpoint, Namespace: namespace}
|
||||||
Type: "service",
|
if err := h.auth.Verify(acc, res); err == nil {
|
||||||
Name: "go.micro.web",
|
// The account has the necessary permissions to access the resource
|
||||||
Endpoint: req.URL.Path,
|
|
||||||
Namespace: namespace,
|
|
||||||
})
|
|
||||||
|
|
||||||
// The account has the necessary permissions to access the resource
|
|
||||||
if err == nil {
|
|
||||||
h.handler.ServeHTTP(w, req)
|
h.handler.ServeHTTP(w, req)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/api/server/auth"
|
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/micro/go-micro/v2/api/server"
|
"github.com/micro/go-micro/v2/api/server"
|
||||||
|
"github.com/micro/go-micro/v2/api/server/auth"
|
||||||
"github.com/micro/go-micro/v2/api/server/cors"
|
"github.com/micro/go-micro/v2/api/server/cors"
|
||||||
"github.com/micro/go-micro/v2/logger"
|
"github.com/micro/go-micro/v2/logger"
|
||||||
)
|
)
|
||||||
@ -25,9 +24,14 @@ type httpServer struct {
|
|||||||
exit chan chan error
|
exit chan chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(address string) server.Server {
|
func NewServer(address string, opts ...server.Option) server.Server {
|
||||||
|
var options server.Options
|
||||||
|
for _, o := range opts {
|
||||||
|
o(&options)
|
||||||
|
}
|
||||||
|
|
||||||
return &httpServer{
|
return &httpServer{
|
||||||
opts: server.Options{},
|
opts: options,
|
||||||
mux: http.NewServeMux(),
|
mux: http.NewServeMux(),
|
||||||
address: address,
|
address: address,
|
||||||
exit: make(chan chan error),
|
exit: make(chan chan error),
|
||||||
@ -49,7 +53,7 @@ func (s *httpServer) Init(opts ...server.Option) error {
|
|||||||
|
|
||||||
func (s *httpServer) Handle(path string, handler http.Handler) {
|
func (s *httpServer) Handle(path string, handler http.Handler) {
|
||||||
h := handlers.CombinedLoggingHandler(os.Stdout, handler)
|
h := handlers.CombinedLoggingHandler(os.Stdout, handler)
|
||||||
h = auth.CombinedAuthHandler(handler)
|
h = auth.CombinedAuthHandler(s.opts.Namespace, s.opts.Resolver, handler)
|
||||||
|
|
||||||
if s.opts.EnableCORS {
|
if s.opts.EnableCORS {
|
||||||
h = cors.CombinedCORSHandler(h)
|
h = cors.CombinedCORSHandler(h)
|
||||||
|
@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
|
||||||
|
"github.com/micro/go-micro/v2/api/resolver"
|
||||||
"github.com/micro/go-micro/v2/api/server/acme"
|
"github.com/micro/go-micro/v2/api/server/acme"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,6 +16,8 @@ type Options struct {
|
|||||||
EnableTLS bool
|
EnableTLS bool
|
||||||
ACMEHosts []string
|
ACMEHosts []string
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
|
Namespace string
|
||||||
|
Resolver resolver.Resolver
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnableCORS(b bool) Option {
|
func EnableCORS(b bool) Option {
|
||||||
@ -52,3 +55,15 @@ func TLSConfig(t *tls.Config) Option {
|
|||||||
o.TLSConfig = t
|
o.TLSConfig = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Namespace(n string) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.Namespace = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Resolver(r resolver.Resolver) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.Resolver = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user