Removed godep dependency.

Golang community are discuting a vendor aproach to go dependencies. This
change will come as experimental in go 1.5. For now I am removing the
godep dependency manager and using a vendor aproach.

I still have to use the full path when importing dependencies, but when
go1.5 released I just have to rename the imports and use a -vendor
prefix when building the project.
This commit is contained in:
claudemiro
2015-06-13 09:11:55 -03:00
parent 10e6048d11
commit 228ed284d9
68 changed files with 347 additions and 82 deletions
+12
View File
@@ -0,0 +1,12 @@
language: go
go:
- 1.2
- 1.3
- tip
install:
- go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v
- go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v
- go get code.google.com/p/go.tools/cmd/cover
- go build -v ./...
script:
- go test -v -cover ./...
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2014 Carl Jackson ([email protected]), Matt Silverlock ([email protected])
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+110
View File
@@ -0,0 +1,110 @@
# goji/httpauth [![GoDoc](https://godoc.org/github.com/goji/httpauth?status.png)](https://godoc.org/github.com/goji/httpauth) [![Build Status](https://travis-ci.org/goji/httpauth.svg)](https://travis-ci.org/goji/httpauth)
httpauth currently provides [HTTP Basic Authentication middleware](http://tools.ietf.org/html/rfc2617) for Go.
Note that httpauth is completely compatible with [Goji](https://goji.io/), a minimal web framework for Go, but as it satisfies http.Handler it can be used beyond Goji itself.
## Example
httpauth provides a `SimpleBasicAuth` function to get you up and running. Particularly ideal for development servers.
Note that HTTP Basic Authentication credentials are sent over the wire "in the clear" (read: plaintext!) and therefore should not be considered a robust way to secure a HTTP server. If you're after that, you'll need to use SSL/TLS ("HTTPS") at a minimum.
### Goji
```go
package main
import(
"net/http"
"github.com/zenazn/goji/web"
"github.com/zenazn/goji/web/middleware"
)
func main() {
goji.Use(httpauth.SimpleBasicAuth("dave", "somepassword"))
goji.Use(SomeOtherMiddleware)
// myHandler requires HTTP Basic Auth
goji.Get("/thing", myHandler)
goji.Serve()
}
```
If you're looking for a little more control over the process, you can instead pass a `httpauth.AuthOptions` struct to `httpauth.BasicAuth` instead. This allows you to:
* Configure the authentication realm
* Provide your own UnauthorizedHandler (anything that satisfies `http.Handler`) so you can return a better looking 401 page.
```go
func main() {
authOpts := httpauth.AuthOptions{
Realm: "DevCo",
User: "dave",
Password: "plaintext!",
UnauthorizedHandler: myUnauthorizedHandler,
}
goji.Use(BasicAuth(authOpts))
goji.Use(SomeOtherMiddleware)
goji.Get("/thing", myHandler)
goji.Serve()
}
```
### gorilla/mux
Since it's all `http.Handler`, httpauth works with gorilla/mux (and most other routers) as well:
```go
package main
import (
"net/http"
"github.com/goji/httpauth"
"github.com/gorilla/mux"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/", myHandler)
http.Handle("/", httpauth.SimpleBasicAuth("dave", "somepassword")(r))
http.ListenAndServe(":7000", nil)
}
func myHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
}
```
### net/http
If you're using vanilla net/http:
```go
package main
import(
"net/http"
"github.com/goji/httpauth"
)
func main() {
http.Handle("/", httpauth.SimpleBasicAuth("dave", "somepassword")(http.HandlerFunc(hello)))
http.ListenAndServe(":7000", nil)
}
```
## Contributing
Send a pull request! Note that features on the (informal) roadmap include HTTP Digest Auth and the potential for supplying your own user/password comparison function.
+160
View File
@@ -0,0 +1,160 @@
package httpauth
import (
"bytes"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"fmt"
"net/http"
"strings"
)
type basicAuth struct {
h http.Handler
opts AuthOptions
}
// AuthOptions stores the configuration for HTTP Basic Authentication.
//
// A http.Handler may also be passed to UnauthorizedHandler to override the
// default error handler if you wish to serve a custom template/response.
type AuthOptions struct {
Realm string
User string
Password string
UnauthorizedHandler http.Handler
}
// Satisfies the http.Handler interface for basicAuth.
func (b basicAuth) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Check if we have a user-provided error handler, else set a default
if b.opts.UnauthorizedHandler == nil {
b.opts.UnauthorizedHandler = http.HandlerFunc(defaultUnauthorizedHandler)
}
// Check that the provided details match
if b.authenticate(r) == false {
b.requestAuth(w, r)
return
}
// Call the next handler on success.
b.h.ServeHTTP(w, r)
}
// authenticate retrieves and then validates the user:password combination provided in
// the request header. Returns 'false' if the user has not successfully authenticated.
func (b *basicAuth) authenticate(r *http.Request) bool {
const basicScheme string = "Basic "
// Confirm the request is sending Basic Authentication credentials.
auth := r.Header.Get("Authorization")
if !strings.HasPrefix(auth, basicScheme) {
return false
}
// Get the plain-text username and password from the request
// The first six characters are skipped - e.g. "Basic ".
str, err := base64.StdEncoding.DecodeString(auth[len(basicScheme):])
if err != nil {
return false
}
// Split on the first ":" character only, with any subsequent colons assumed to be part
// of the password. Note that the RFC2617 standard does not place any limitations on
// allowable characters in the password.
creds := bytes.SplitN(str, []byte(":"), 2)
if len(creds) != 2 {
return false
}
// Equalize lengths of supplied and required credentials
// by hashing them
givenUser := sha256.Sum256(creds[0])
givenPass := sha256.Sum256(creds[1])
requiredUser := sha256.Sum256([]byte(b.opts.User))
requiredPass := sha256.Sum256([]byte(b.opts.Password))
// Compare the supplied credentials to those set in our options
if subtle.ConstantTimeCompare(givenUser[:], requiredUser[:]) == 1 &&
subtle.ConstantTimeCompare(givenPass[:], requiredPass[:]) == 1 {
return true
}
return false
}
// Require authentication, and serve our error handler otherwise.
func (b *basicAuth) requestAuth(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", fmt.Sprintf(`Basic realm=%q`, b.opts.Realm))
b.opts.UnauthorizedHandler.ServeHTTP(w, r)
}
// defaultUnauthorizedHandler provides a default HTTP 401 Unauthorized response.
func defaultUnauthorizedHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
// BasicAuth provides HTTP middleware for protecting URIs with HTTP Basic Authentication
// as per RFC 2617. The server authenticates a user:password combination provided in the
// "Authorization" HTTP header.
//
// Example:
//
// package main
//
// import(
// "net/http"
// "github.com/zenazn/goji"
// "github.com/zenazn/goji/web/httpauth"
// )
//
// func main() {
// basicOpts := httpauth.AuthOptions{
// Realm: "Restricted",
// User: "Dave",
// Password: "ClearText",
// }
//
// goji.Use(httpauth.BasicAuth(basicOpts), SomeOtherMiddleware)
// goji.Get("/thing", myHandler)
// }
//
// Note: HTTP Basic Authentication credentials are sent in plain text, and therefore it does
// not make for a wholly secure authentication mechanism. You should serve your content over
// HTTPS to mitigate this, noting that "Basic Authentication" is meant to be just that: basic!
func BasicAuth(o AuthOptions) func(http.Handler) http.Handler {
fn := func(h http.Handler) http.Handler {
return basicAuth{h, o}
}
return fn
}
// SimpleBasicAuth is a convenience wrapper around BasicAuth. It takes a user and password, and
// returns a pre-configured BasicAuth handler using the "Restricted" realm and a default 401 handler.
//
// Example:
//
// package main
//
// import(
// "net/http"
// "github.com/zenazn/goji/web/httpauth"
// )
//
// func main() {
//
// goji.Use(httpauth.SimpleBasicAuth("dave", "somepassword"), SomeOtherMiddleware)
// goji.Get("/thing", myHandler)
// }
//
func SimpleBasicAuth(user, password string) func(http.Handler) http.Handler {
opts := AuthOptions{
Realm: "Restricted",
User: user,
Password: password,
}
return BasicAuth(opts)
}
+44
View File
@@ -0,0 +1,44 @@
package httpauth
import (
"encoding/base64"
"net/http"
"testing"
)
func TestBasicAuthAuthenticate(t *testing.T) {
// Provide a minimal test implementation.
authOpts := AuthOptions{
Realm: "Restricted",
User: "test-user",
Password: "plain-text-password",
}
b := &basicAuth{
opts: authOpts,
}
r := &http.Request{}
r.Method = "GET"
// Provide auth data, but no Authorization header
if b.authenticate(r) != false {
t.Fatal("No Authorization header supplied.")
}
// Initialise the map for HTTP headers
r.Header = http.Header(make(map[string][]string))
// Set a malformed/bad header
r.Header.Set("Authorization", " Basic")
if b.authenticate(r) != false {
t.Fatal("Malformed Authorization header supplied.")
}
// Test correct credentials
auth := base64.StdEncoding.EncodeToString([]byte(b.opts.User + ":" + b.opts.Password))
r.Header.Set("Authorization", "Basic "+auth)
if b.authenticate(r) != true {
t.Fatal("Failed on correct credentials")
}
}