1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
# Example of Router
These examples show you the usage of `router`. You can easily build a web application with it. Or you can make your own midwares such as custom logger, metrics, or any one you want.
### Basic Authentication
This Basic Authentication example uses `simple-scrypt` for password hashing:
go get -u github.com/elithrar/simple-scrypt
Password hashing is used so that if your data store is compromised, the attackers will only have access to hashed passwords, which (if the hash is not itself compromised) will not be able to revert to the original plain text password.
After you have hashed the password and stored the hash in a data store, you should throw away the original plain-text password.
The next time the user attempts to log in, their password will be safely hashed and compared to the saved hash. If the hashes match, then the user will be accepted.
Only use constant time comparison functions that are built into your hash library to compare secret strings like passwords or hashes to prevent timing attacks.
```go
package main
import (
"encoding/base64"
"fmt"
"log"
"strings"
"github.com/fasthttp/router"
"github.com/elithrar/simple-scrypt"
"github.com/valyala/fasthttp"
)
// basicAuth returns the username and password provided in the request's
// Authorization header, if the request uses HTTP Basic Authentication.
// See RFC 2617, Section 2.
func basicAuth(ctx *fasthttp.RequestCtx) (username, password string, ok bool) {
auth := ctx.Request.Header.Peek("Authorization")
if auth == nil {
return
}
return parseBasicAuth(string(auth))
}
// parseBasicAuth parses an HTTP Basic Authentication string.
// "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" returns ("Aladdin", "open sesame", true).
func parseBasicAuth(auth string) (username, password string, ok bool) {
const prefix = "Basic "
if !strings.HasPrefix(auth, prefix) {
return
}
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if err != nil {
return
}
cs := string(c)
s := strings.IndexByte(cs, ':')
if s < 0 {
return
}
return cs[:s], cs[s+1:], true
}
// BasicAuth is the basic auth handler
func BasicAuth(h fasthttp.RequestHandler, requiredUser string, requiredPasswordHash []byte) fasthttp.RequestHandler {
return fasthttp.RequestHandler(func(ctx *fasthttp.RequestCtx) {
// Get the Basic Authentication credentials
user, password, hasAuth := basicAuth(ctx)
// WARNING:
// DO NOT use plain-text passwords for real apps.
// A simple string comparison using == is vulnerable to a timing attack.
// Instead, use the hash comparison function found in your hash library.
// This example uses scrypt, which is a solid choice for secure hashing:
// go get -u github.com/elithrar/simple-scrypt
if hasAuth && user == requiredUser {
// Uses the parameters from the existing derived key. Return an error if they don't match.
err := scrypt.CompareHashAndPassword(requiredPasswordHash, []byte(password))
if err != nil {
// log error and request Basic Authentication again below.
log.Fatal(err)
} else {
// Delegate request to the given handle
h(ctx)
return
}
}
// Request Basic Authentication otherwise
ctx.Error(fasthttp.StatusMessage(fasthttp.StatusUnauthorized), fasthttp.StatusUnauthorized)
ctx.Response.Header.Set("WWW-Authenticate", "Basic realm=Restricted")
})
}
// Index is the index handler
func Index(ctx *fasthttp.RequestCtx) {
fmt.Fprint(ctx, "Not protected!\n")
}
// Protected is the Protected handler
func Protected(ctx *fasthttp.RequestCtx) {
fmt.Fprint(ctx, "Protected!\n")
}
func main() {
user := "gordon"
pass := "secret!"
// generate a hashed password from the password above:
hashedPassword, err := scrypt.GenerateFromPassword([]byte(pass), scrypt.DefaultParams)
if err != nil {
log.Fatal(err)
}
r := router.New()
r.GET("/", Index)
r.GET("/protected/", BasicAuth(Protected, user, hashedPassword))
log.Fatal(fasthttp.ListenAndServe(":8080", r.Handler))
}
```
|