OSDN Git Service

Merge branch 'master' into wallet-store-interface-account
[bytom/vapor.git] / vendor / github.com / gin-gonic / gin / auth.go
diff --git a/vendor/github.com/gin-gonic/gin/auth.go b/vendor/github.com/gin-gonic/gin/auth.go
new file mode 100644 (file)
index 0000000..9ed81b5
--- /dev/null
@@ -0,0 +1,96 @@
+// Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
+// Use of this source code is governed by a MIT style
+// license that can be found in the LICENSE file.
+
+package gin
+
+import (
+       "crypto/subtle"
+       "encoding/base64"
+       "net/http"
+       "strconv"
+)
+
+// AuthUserKey is the cookie name for user credential in basic auth.
+const AuthUserKey = "user"
+
+// Accounts defines a key/value for user/pass list of authorized logins.
+type Accounts map[string]string
+
+type authPair struct {
+       value string
+       user  string
+}
+
+type authPairs []authPair
+
+func (a authPairs) searchCredential(authValue string) (string, bool) {
+       if authValue == "" {
+               return "", false
+       }
+       for _, pair := range a {
+               if pair.value == authValue {
+                       return pair.user, true
+               }
+       }
+       return "", false
+}
+
+// BasicAuthForRealm returns a Basic HTTP Authorization middleware. It takes as arguments a map[string]string where
+// the key is the user name and the value is the password, as well as the name of the Realm.
+// If the realm is empty, "Authorization Required" will be used by default.
+// (see http://tools.ietf.org/html/rfc2617#section-1.2)
+func BasicAuthForRealm(accounts Accounts, realm string) HandlerFunc {
+       if realm == "" {
+               realm = "Authorization Required"
+       }
+       realm = "Basic realm=" + strconv.Quote(realm)
+       pairs := processAccounts(accounts)
+       return func(c *Context) {
+               // Search user in the slice of allowed credentials
+               user, found := pairs.searchCredential(c.requestHeader("Authorization"))
+               if !found {
+                       // Credentials doesn't match, we return 401 and abort handlers chain.
+                       c.Header("WWW-Authenticate", realm)
+                       c.AbortWithStatus(http.StatusUnauthorized)
+                       return
+               }
+
+               // The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using
+               // c.MustGet(gin.AuthUserKey).
+               c.Set(AuthUserKey, user)
+       }
+}
+
+// BasicAuth returns a Basic HTTP Authorization middleware. It takes as argument a map[string]string where
+// the key is the user name and the value is the password.
+func BasicAuth(accounts Accounts) HandlerFunc {
+       return BasicAuthForRealm(accounts, "")
+}
+
+func processAccounts(accounts Accounts) authPairs {
+       assert1(len(accounts) > 0, "Empty list of authorized credentials")
+       pairs := make(authPairs, 0, len(accounts))
+       for user, password := range accounts {
+               assert1(user != "", "User can not be empty")
+               value := authorizationHeader(user, password)
+               pairs = append(pairs, authPair{
+                       value: value,
+                       user:  user,
+               })
+       }
+       return pairs
+}
+
+func authorizationHeader(user, password string) string {
+       base := user + ":" + password
+       return "Basic " + base64.StdEncoding.EncodeToString([]byte(base))
+}
+
+func secureCompare(given, actual string) bool {
+       if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 {
+               return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1
+       }
+       // Securely compare actual to itself to keep constant time, but always return false.
+       return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false
+}